chiark / gitweb /
Initial revision
[ssr] / StraySrc / Libraries / Sapphire / s / drag
1 ;
2 ; drag.s
3 ;
4 ; Support code for dragging operations (MDW)
5 ;
6 ; © 1995-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:akbd
37                 GET     sapphire:idle
38                 GET     sapphire:intKeys
39                 GET     sapphire:sapphire
40                 GET     sapphire:screen
41                 GET     sapphire:win
42
43 ;----- Main code ------------------------------------------------------------
44
45                 AREA    |Sapphire$$Code|,CODE,READONLY
46
47 ; --- drag_start ---
48 ;
49 ; On entry:     R0 == window containing the drag
50 ;               R1 == flags word (see flags below)
51 ;               R2 == pointer to drag routine
52 ;               R3 == magic number to pass in R9
53 ;               R4 == value to pass to routine in R10
54 ;               R5 == value to pass to routine in R12
55 ;
56 ; On exit:      --
57 ;
58 ; Use:          Starts a drag operation.  Any outstanding drag operation
59 ;               is cancelled on the assumption that someone stole our
60 ;               UserDragBox event.
61
62                 EXPORT  drag_start
63 drag_start      ROUT
64
65                 STMFD   R13!,{R0-R7,R12,R14}    ;Save some registers
66                 WSPACE  drag__wSpace            ;Find my workspace address
67
68                 ; --- Cancel any current drag operation ---
69
70                 LDR     R14,drag__window        ;Load current window
71                 CMP     R14,#0                  ;Is there one defined?
72                 BLNE    drag_cancel             ;Yes -- cancel it then
73
74                 ; --- Ensure that this isn't a silly ---
75                 ;
76                 ; Rather irritatingly, the WIMP's drag-detection is a little
77                 ; suspect; it thinks that moving the pointer outside of
78                 ; a window while the button is held down is actually a drag.
79                 ; We try to hack around this little problem.
80
81                 SWI     OS_Mouse                ;Read the current mouse pos.
82                 CMP     R2,#0                   ;Are any buttons pressed?
83                 LDMEQFD R13!,{R0-R7,R12,PC}^    ;No -- do nothing then
84
85                 ; --- Set up handlers for new drag op ---
86
87                 MOV     R0,#0                   ;Call me very often please
88                 ADR     R1,drag__idles          ;Point to the handler
89                 MOV     R2,#0                   ;Nothing to pass in R10
90                 MOV     R3,R12                  ;Pass workspace in R12
91                 BL      idle_handler            ;Install the handler
92                 LDMVSFD R13!,{R0-R7,R12,PC}^    ;If it failed, return now
93
94                 ; --- Set up all the new information ---
95
96                 LDMIA   R13,{R0-R3}             ;Load information off stack
97                 STMIA   R12,{R0-R5}             ;Save all that lot away
98
99                 MOV     R0,#&3F                 ;Reset the dash pattern
100                 STRB    R0,drag__dash           ;This is the current dash
101                 STRB    R0,drag__oldDash        ;And the previous one
102                 BL      drag_setDash            ;Make it the current pattern
103
104                 SWI     OS_ReadMonotonicTime    ;Find the current time
105                 STR     R0,drag__lastTime       ;And store that away too
106
107                 ; --- Now read the current position of the drag ---
108
109                 SUB     R13,R13,#44             ;Make space for window state
110                 LDR     R14,drag__window        ;Load the window handle
111                 STR     R14,[R13,#0]            ;Save it in the block
112                 MOV     R1,R13                  ;Point to this block
113                 SWI     Wimp_GetWindowState     ;Read the window's position
114
115                 BL      drag__find              ;Find the current position
116                 ADR     R14,drag__startPos      ;Point to the current posn
117                 STMIA   R14!,{R4,R5}            ;Load the coordinates out
118                 STMIA   R14!,{R4,R5}            ;Store them in start position
119
120                 MOV     R0,#drEvent_draw        ;Do some drawing please
121                 BL      drag__draw              ;And draw the dash box
122                 ADD     R13,R13,#44             ;Restore the stack pointer
123                 LDMFD   R13!,{R0-R7,R12,PC}^    ;Return to caller finally
124
125                 LTORG
126
127 ; --- drag_scroll ---
128 ;
129 ; On entry:     R1 == pointer to window state block
130 ;
131 ; On exit:      R2,R3 == new scroll positions to set
132 ;               R14 == R1+20 (pointer to scroll offsets)
133 ;
134 ; Use:          Works out the scroll positions which should be set to auto-
135 ;               scroll the window.  The algorithm is simple: the window is
136 ;               scrolled so that the point beneath the mouse pointer is
137 ;               within the window's visible work area.
138
139                 EXPORT  drag_scroll
140 drag_scroll     ROUT
141
142                 STMFD   R13!,{R0,R1,R4-R7,R14}  ;Save some registers
143
144                 ; --- Find the mouse pointer position ---
145
146                 LDMIB   R1!,{R4-R7}             ;Load the bounding box out
147                 LDMIB   R1!,{R2,R3}             ;And the current scroll pos
148                 SUB     R13,R13,#20             ;Make a PointerInfo block
149                 MOV     R1,R13                  ;Point at this
150                 SWI     Wimp_GetPointerInfo     ;Read the information
151                 LDMIA   R13,{R0,R1}             ;Load the current position
152
153                 ; --- Now fiddle the scroll positions ---
154
155                 SUBS    R14,R0,R4               ;Compare x to left side
156                 ADDLT   R2,R2,R14               ;If too far left, then scroll
157                 SUBS    R14,R1,R5               ;Compare y to bottom
158                 ADDLT   R3,R3,R14               ;If too low, then scroll
159                 SUBS    R14,R0,R6               ;Compare x to right side
160                 ADDGT   R2,R2,R14               ;If too far right, scroll
161                 SUBS    R14,R1,R7               ;Compare y to top
162                 ADDGT   R3,R3,R14               ;If too high, then scroll
163
164                 ; --- Return everything to caller ---
165
166                 ADD     R13,R13,#20             ;Restore the stack pointer
167                 LDR     R14,[R13,#4]            ;Load the pointer out
168                 ADD     R14,R14,#20             ;Point to scroll offsets
169                 LDMFD   R13!,{R0,R1,R4-R7,PC}^  ;And return to caller
170
171                 LTORG
172
173 ; --- drag__dispatch ---
174 ;
175 ; On entry:     R0 == event code
176 ;               R1-R7 depend on event
177 ;
178 ; On exit:      --
179 ;
180 ; Use:          Dispatches a drag event to the current handler.
181
182 drag__dispatch  ROUT
183
184                 STMFD   R13!,{R8-R10,R12,R14}   ;Save some registers
185                 ADR     R14,drag__handler       ;Point to the handler
186                 LDMIA   R14,{R8-R10,R12}        ;Load the registers out
187                 MOV     R14,PC                  ;Set up return address
188                 MOV     PC,R8                   ;Call the routine nicely
189                 LDMFD   R13!,{R8-R10,R12,PC}^   ;And return to caller
190
191                 LTORG
192
193 ; --- drag__draw ---
194 ;
195 ; On entry:     R0 == event code to pass
196 ;               R1 == pointer to window state block (44 bytes required)
197 ;
198 ; On exit:      --
199 ;
200 ; Use:          Updates a window using the given event.
201
202 drag__draw      ROUT
203
204                 STMFD   R13!,{R0-R9,R14}        ;Save some registers
205                 MOV     R8,R0                   ;Look after the event code
206                 LDR     R9,[R1,#28]             ;Load the `behind' pointer
207
208                 ; --- Build the update block ---
209
210                 LDMIB   R1,{R2-R5,R7,R14}       ;Load the values out of it
211
212                 SUB     R6,R2,R7                ;Find the x origin position
213                 SUB     R4,R4,R2                ;Find the window width
214                 MOV     R2,R7                   ;Get left side of update box
215                 ADD     R4,R2,R4                ;Get right side of update box
216
217                 SUB     R7,R5,R14               ;Find the y origin position
218                 SUB     R3,R5,R3                ;Find the window height
219                 MOV     R5,R14                  ;Get top of update box
220                 SUB     R3,R5,R3                ;Get bottom of update box
221
222                 STMIB   R1,{R2-R5}              ;Save the box back
223
224                 ; --- Set up other registers for the job ---
225
226                 ADR     R14,drag__startPos      ;Find the start position
227                 LDMIA   R14,{R2-R5}             ;Load the positions out
228
229                 ; --- Finally do the actual update ---
230
231                 SWI     Wimp_UpdateWindow       ;Start the update job
232                 CMP     R0,#0                   ;Is there anything to do?
233                 BEQ     %90drag__draw           ;No -- then skip ahead
234
235 00              MOV     R0,R8                   ;Get caller's event code
236                 BL      drag__dispatch          ;Call the event handler
237                 SWI     Wimp_GetRectangle       ;Get the next rectangle
238                 CMP     R0,#0                   ;Is there anything left?
239                 BNE     %b00                    ;Yes -- loop back to do it
240
241                 ; --- Tidy up and return to caller ---
242
243 90drag__draw    STR     R9,[R1,#28]             ;Store `behind' pointer back
244                 LDMFD   R13!,{R0-R9,PC}^        ;And return to caller
245
246                 LTORG
247
248 ; --- drag__find ---
249 ;
250 ; On entry:     R1 == pointer to window state block
251 ;
252 ; On exit:      R4,R5 == coordinates, suitably transformed
253 ;               R6,R7 == window origin coordinates
254 ;               CS if mouse button still down, else CC
255 ;
256 ; Use:          Locates the mouse pointer within the window.
257
258 drag__find      ROUT
259
260                 STMFD   R13!,{R0-R3,R14}        ;Save some registers
261                 MOV     R2,R1                   ;Remember initial pointer
262                 SUB     R13,R13,#20             ;Make space for pointer info
263                 MOV     R1,R13                  ;Point to this block
264                 SWI     Wimp_GetPointerInfo     ;Find the pointer position
265                 MOV     R1,R2                   ;Point to original block
266
267                 ; --- Set up for calling event handler ---
268
269                 LDR     R2,[R1,#4]              ;Load the left hand side
270                 ADD     R14,R1,#16              ;Find top and scroll position
271                 LDMIA   R14,{R5-R7}             ;Load them out nicely
272                 SUB     R6,R2,R6                ;Find the x origin position
273                 SUB     R7,R5,R7                ;And the y origin position
274
275                 LDMIA   R13,{R4,R5}             ;Load the coordinates out
276                 SUB     R4,R4,R6                ;Translate to window coords
277                 SUB     R5,R5,R7                ;Do that to y coord too
278                 MOV     R0,#drEvent_trans       ;Get handler to translate
279                 BL      drag__dispatch          ;Go and do that then
280
281                 ; --- Tidy up and return ---
282
283                 LDR     R14,[R13,#8]            ;Load the mouse status
284                 CMP     R14,#0                  ;Are all buttons released?
285                 ADD     R13,R13,#20             ;Restore the stack block
286                 LDMFD   R13!,{R0-R3,R14}        ;Restore registers
287                 ORRNES  PC,R14,#C_flag          ;If button pressed, return CS
288                 BICEQS  PC,R14,#C_flag          ;Else return CC
289
290                 LTORG
291
292 ; --- drag__getPosition ---
293 ;
294 ; On entry:     R1 == pointer to window state block
295 ;               R4,R5 == new position
296 ;               R6,R7 == window origin position
297 ;
298 ; On exit:      R4,R5 == new position, translated further
299 ;
300 ; Use:          Reads the position of the current drag operation.  This
301 ;               allows the client to do clever things like gridlocking and
302 ;               autoscrolling.
303
304 drag__getPosition ROUT
305
306                 STMFD   R13!,{R0,R2,R3,R14}     ;Save some registers
307                 ADR     R14,drag__startPos      ;Find the start position
308                 LDMIA   R14,{R2,R3}             ;Load those coordinates out
309                 MOV     R0,#drEvent_getPos      ;Tell client to translate
310                 BL      drag__dispatch          ;Send the event off
311                 LDMFD   R13!,{R0,R2,R3,PC}^     ;And return to caller
312
313                 LTORG
314
315 ; --- drag_setDash ---
316 ;
317 ; On entry:     R0 == dash pattern byte
318 ;
319 ; On exit:      --
320 ;
321 ; Use:          Sets the dash pattern to be the given value.
322
323                 EXPORT  drag_setDash
324 drag_setDash    ROUT
325
326                 STMFD   R13!,{R0-R2,R14}        ;Save some registers
327
328                 ; --- Build VDU block ---
329
330                 AND     R0,R0,#&FF              ;Clear top bits of R0
331                 ORR     R1,R0,R0,LSL #8         ;Duplicate the byte
332                 ORR     R1,R1,R1,LSL #16        ;Fill a word with it
333                 MOV     R0,#23                  ;Get the VDU command code
334                 ORR     R0,R0,#6<<8             ;OR in the command type
335                 ORR     R0,R0,R1,LSL #16        ;Put in first two patterns
336                 MOV     R2,R1,LSR #16           ;Put in last two patterns
337                 STMIA   R11,{R0-R2}             ;Save that on the stack
338
339                 ; --- Set the dash pattern length ---
340
341                 MOV     R0,#163                 ;Write general graphics info
342                 MOV     R1,#242                 ;Set dash pattern length
343                 MOV     R2,#8                   ;Set the repeat length
344                 SWI     OS_Byte                 ;Set the length then
345
346                 ; --- Now set the dash pattern itself ---
347
348                 MOV     R0,R11                  ;Point to my VDU block
349                 MOV     R1,#10                  ;Size of block in bytes
350                 SWI     OS_WriteN               ;Write that to the VDU things
351                 LDMFD   R13!,{R0-R2,PC}^        ;And return to caller
352
353                 LTORG
354
355 ; --- drag__idles ---
356 ;
357 ; On entry:     --
358 ;
359 ; On exit:      --
360 ;
361 ; Use:          Handles idle events during a drag operation.
362
363 drag__idles     ROUT
364
365                 STMFD   R13!,{R0-R7,R14}        ;Save some registers
366
367                 ; --- Check for a cancelled drag ---
368
369                 MOV     R0,#intk_Esc            ;Get the Escape kep code
370                 BL      akbd_test               ;Test the key
371                 BCS     %70drag__idles          ;Cancelled -- abort it then
372
373                 ; --- Update the dash pattern ---
374
375                 SWI     OS_ReadMonotonicTime    ;Read the current time
376                 LDR     R14,drag__lastTime      ;Load the old time nicely
377                 SUB     R0,R0,R14               ;Find the difference
378                 MOV     R0,R0,LSR #2            ;Divide by 4
379                 ADD     R14,R14,R0,LSL #2       ;Add on rounded value
380                 STR     R14,drag__lastTime      ;Save that back
381
382                 LDRB    R14,drag__dash          ;Load the dash position
383                 STRB    R14,drag__oldDash       ;This is now the old one
384                 MOV     R0,R0,LSL #1            ;Multiply difference by 2
385                 MOV     R0,R14,ROR R0           ;Rotate the dash pattern
386                 ORR     R0,R0,R0,ROR #24        ;Fake an 8-bit rotate
387                 ORR     R0,R0,R0,ROR #16        ;Make sure it's done properly
388                 STRB    R0,drag__dash           ;This is the new pattern
389
390                 ; --- Read the new position ---
391
392                 SUB     R13,R13,#44             ;Make a window state block
393                 LDR     R14,drag__window        ;Load the window handle out
394                 STR     R14,[R13,#0]            ;Store handle in there
395                 MOV     R1,R13                  ;Point to the block
396                 SWI     Wimp_GetWindowState     ;Read the window information
397
398                 BL      drag__find              ;Find the new position
399                 BL      drag__getPosition       ;Do any exra processing reqd
400                 BCC     %50drag__idles          ;If done, skip onwards
401
402                 ; --- Work out what needs to be done ---
403
404                 ADR     R14,drag__currPos       ;Find the current position
405                 LDMIA   R14,{R2,R3}             ;Load that out
406                 CMP     R2,R4                   ;Has the drag box moved?
407                 CMPEQ   R3,R5                   ;Check both coordinates
408                 BEQ     %30drag__idles          ;No -- handle speciallt
409
410                 ; --- Force the update of the drag box ---
411
412                 LDRB    R0,drag__oldDash        ;Get the old dash pattern
413                 BL      drag_setDash            ;Set this as the pattern
414                 MOV     R0,#drEvent_undraw      ;Tell client to undraw
415                 BL      drag__draw              ;Go and do that then
416
417                 ; --- Now draw the new one ---
418
419                 ADR     R14,drag__currPos       ;Find the current position
420                 STMIA   R14,{R4,R5}             ;Save new position in there
421                 LDRB    R0,drag__dash           ;Load the new dash pattern
422                 BL      drag_setDash            ;Set this as the pattern
423                 MOV     R0,#drEvent_draw        ;Tell client to draw
424                 BL      drag__draw              ;Go and do that then
425                 B       %90drag__idles          ;Now go and tidy up
426
427                 ; --- Update the drag box in place ---
428
429 30drag__idles   LDR     R14,drag__flags         ;Load any interesting flags
430                 TST     R14,#drFlag_noUpdate    ;Do we send update events?
431                 BNE     %90drag__idles          ;No -- then do nothing
432
433                 LDR     R0,drag__oldDash        ;Load the two dash patterns
434                 EOR     R0,R0,R0,LSR #8         ;Exclusive OR them together
435                 BL      drag_setDash            ;Set this as the pattern
436                 MOV     R0,#drEvent_update      ;Tell client to update drag
437                 BL      drag__draw              ;Go and do that then
438                 B       %90drag__idles          ;Now go and tidy up
439
440                 ; --- Tidy up at the end of the drag ---
441
442 50drag__idles   LDRB    R0,drag__oldDash        ;Get the old dash pattern
443                 BL      drag_setDash            ;Set this as the pattern
444                 MOV     R0,#drEvent_undraw      ;Now remove the drag box
445                 BL      drag__draw              ;Go and do that then
446
447                 ADR     R14,drag__startPos      ;Point to start position
448                 LDMIA   R14,{R2-R5}             ;Load all that lot
449                 MOV     R0,#drEvent_done        ;Say it's all over
450                 BL      drag__dispatch          ;Send that to the user
451
452                 ; --- Remove this idle handler ---
453
454                 MOV     R0,#0                   ;We're called very often
455                 ADR     R1,drag__idles          ;Point to the handler
456                 MOV     R2,#0                   ;Passed nothing in R10
457                 MOV     R3,R12                  ;Passed workspace in R12
458                 BL      idle_removeHandler      ;Remove the handler
459
460                 MOV     R14,#0                  ;A convenient zero
461                 STR     R14,drag__window        ;Clear the window handle
462
463                 B       %90drag__idles          ;Now go and tidy up
464
465                 ; --- Cancel the drag ---
466
467 70drag__idles   BL      drag_cancel             ;Cancel the drag
468                 B       %95drag__idles          ;Now go and tidy up
469
470                 ; --- Now tidy up and go home ---
471
472 90drag__idles   ADD     R13,R13,#44             ;Recover any lost stack space
473 95drag__idles   LDMFD   R13!,{R0-R7,PC}^        ;And return to caller
474
475                 LTORG
476
477 ; --- drag_cancel ---
478 ;
479 ; On entry:     --
480 ;
481 ; On exit:      --
482 ;
483 ; Use:          Cancels the current drag operation.
484
485                 EXPORT  drag_cancel
486 drag_cancel     ROUT
487
488                 STMFD   R13!,{R0-R3,R12,R14}    ;Save some registers
489                 WSPACE  drag__wSpace            ;Find my workspace
490
491                 ; --- Make sure this is worth it ---
492
493                 LDR     R14,drag__window        ;Load current drag window
494                 CMP     R14,#0                  ;Is it defined?
495                 LDMEQFD R13!,{R0-R3,R12,PC}^    ;No -- then do nothing
496
497                 ; --- Undraw the drag box ---
498
499                 SUB     R13,R13,#44             ;Drop the stack by a bit
500                 LDR     R14,drag__window        ;Load the window handle out
501                 STR     R14,[R13,#0]            ;Store handle in there
502                 MOV     R1,R13                  ;Point to the block
503                 SWI     Wimp_GetWindowState     ;Read the window information
504                 LDR     R0,drag__dash           ;Load the current dash pos
505                 BL      drag_setDash            ;Set the dash pattern
506                 MOV     R0,#drEvent_undraw      ;Undraw the drag box
507                 BL      drag__draw              ;Go and do that then
508                 MOV     R0,#drEvent_cancel      ;Say the drag was cancelled
509                 BL      drag__dispatch          ;Inform the client of this
510
511                 ; --- Now tidy up and return ---
512
513                 MOV     R0,#0                   ;We're called very often
514                 ADR     R1,drag__idles          ;Point to the handler
515                 MOV     R2,#0                   ;Passed nothing in R10
516                 MOV     R3,R12                  ;Passed workspace in R12
517                 BL      idle_removeHandler      ;Remove the handler
518
519                 MOV     R14,#0                  ;A convenient zero
520                 STR     R14,drag__window        ;Clear the window handle
521
522                 ADD     R13,R13,#44             ;Restore the stack pointer
523                 LDMFD   R13!,{R0-R3,R12,PC}^    ;And return to caller
524
525                 LTORG
526
527 ; --- drag_redraw ---
528 ;
529 ; On entry:     R1 == pointer to redraw block
530 ;
531 ; On exit:      --
532 ;
533 ; Use:          Redraws the drag box, if the redraw takes place in the
534 ;               currently dragging window.
535
536                 EXPORT  drag_redraw
537 drag_redraw     ROUT
538
539                 STMFD   R13!,{R0-R7,R12,R14}    ;Save some registers
540                 WSPACE  drag__wSpace            ;Find the workspace address
541
542                 ; --- Make sure there's something to do ---
543
544                 LDR     R0,[R1,#0]              ;Load the window handle
545                 LDR     R14,drag__window        ;Load current drag window
546                 CMP     R0,R14                  ;Do these match up?
547                 LDMNEFD R13!,{R0-R7,R12,PC}^    ;No -- do nothing then
548
549                 ; --- Set up registers ---
550
551                 LDR     R2,[R1,#4]              ;Load left hand side
552                 ADD     R14,R1,#16              ;Find top and scroll
553                 LDMIA   R14,{R5-R7}             ;Load that lot out
554                 SUB     R6,R2,R6                ;Find the x origin pos
555                 SUB     R7,R5,R7                ;And the y origin pos
556                 ADR     R14,drag__startPos      ;Find the start position
557                 LDMIA   R14,{R2-R5}             ;Load position out nicely
558
559                 ; --- Now do the drawing ---
560
561                 LDRB    R0,drag__dash           ;Load current dash pattern
562                 BL      drag_setDash            ;Set the dash pattern
563                 MOV     R0,#drEvent_draw        ;Now do some drawing
564                 BL      drag__dispatch          ;Send to event handler
565                 LDMFD   R13!,{R0-R7,R12,PC}^    ;Now return to caller
566
567                 LTORG
568
569 ; --- drag_eorColour ---
570 ;
571 ; On entry:     R0 == colour A
572 ;               R1 == colour B
573 ;
574 ; On exit:      --
575 ;
576 ; Use:          Sets the foreground colour to be an EOR colour such that
577 ;               when painted over Wimp colour A, it appears as Wimp colour B.
578
579                 EXPORT  drag_eorColour
580 drag_eorColour  ROUT
581
582                 STMFD   R13!,{R0-R3,R14}        ;Save some registers
583                 MOV     R2,R0,LSL #2            ;Keep the background colour
584                 MOV     R3,R1,LSL #2            ;And the foreground colour
585                 MOV     R1,R11                  ;Point to the block
586                 SWI     Wimp_ReadPalette        ;Read the current palette
587                 LDR     R0,[R11,R2]             ;Load the fore palette entry
588                 SWI     ColourTrans_ReturnColourNumber
589                 MOV     R2,R0                   ;Save the colour number
590                 LDR     R0,[R11,R3]             ;Load the back palette entry
591                 SWI     ColourTrans_ReturnColourNumber
592                 EOR     R1,R0,R2                ;Get the EOR colour number
593                 MOV     R0,#3                   ;Set EOR colour please
594                 SWI     XOS_SetColour           ;Set the colour, please
595                 BVC     %90drag_eorColour       ;If it worked, return
596
597                 ; --- We must be running RISC OS 2 ---
598                 ;
599                 ; This is very tedious -- we have to set the colour by hand.
600
601                 BL      screen_getInfo          ;Read the screen cache
602                 LDR     R0,[R0,#screen_bpp]     ;Load the current BPP
603                 CMP     R0,#8                   ;Are we in a 256 colour mode?
604                 BEQ     %50drag_eorColour       ;Yes -- handle it specially
605
606                 ; --- Just set the GCOL from R1 ---
607
608                 SWI     OS_WriteI+18            ;Set graphics colour
609                 SWI     OS_WriteI+3             ;Use XOR colour
610                 MOV     R0,R1                   ;Get the colour to set
611                 SWI     OS_WriteC               ;Set the colour
612                 B       %90drag_eorColour       ;Return -- we did it
613
614                 ; --- Set the colour in a 256 colour mode ---
615
616 50              MOV     R0,R1                   ;Get colour in R0
617                 SWI     ColourTrans_ColourNumberToGCOL
618                 MOV     R1,R0                   ;Keep the GCOL safe
619                 SWI     OS_WriteI+18            ;Set graphics colour
620                 SWI     OS_WriteI+3             ;Use XOR colour
621                 MOV     R0,R1,LSR #2            ;Get the GCOL part of it
622                 SWI     OS_WriteC               ;Set the colour
623
624                 ; --- Now set the tint ---
625
626                 MOV     R0,#23                  ;VDU code for tint setting
627                 ORR     R0,R0,#17<<8            ;Subreason code for tint
628                 ORR     R0,R0,#2<<16            ;Set the graphics foreground
629                 ORR     R0,R0,R1,LSL #30        ;Get the tint bits in too
630                 MOV     R1,#0                   ;Other bytes are all 0
631                 MOV     R2,#0                   ;Two words of them
632                 STMIA   R11,{R0-R2}             ;Save them in scratchpad
633                 MOV     R0,R11                  ;Point at them
634                 MOV     R1,#10                  ;VDU 23 is 10 bytes long
635                 SWI     OS_WriteN               ;Write the whole lot out
636
637 90              LDMFD   R13!,{R0-R3,PC}^
638
639                 LTORG
640
641 drag__wSpace    DCD     0
642
643 ;----- Flags ----------------------------------------------------------------
644
645 drFlag_noUpdate EQU     (1<<0)                  ;Don't generate update events
646
647 ;----- Drag handler events --------------------------------------------------
648
649 ; --- Note ---
650 ;
651 ; The events which request that you draw something are called for each
652 ; rectangle of the draw operation -- i.e. do not call Wimp_GetRectangle
653 ; because this is done for you.
654
655                 ^       0
656 drEvent_draw    #       1                       ;Draw dragged object
657                                                 ;R1 == pointer to redraw blk
658                                                 ;R2,R3 == drag start posn
659                                                 ;R4,R5 == drag current posn
660                                                 ;R6,R7 == window origin
661                                                 ;Dash pattern set up
662
663 drEvent_undraw  #       1                       ;Undraw dragged object
664                                                 ;Regs as for drEvent_draw
665                                                 ;Normally use the same code
666
667 drEvent_update  #       1                       ;Redraw dragged object in
668                                                 ;place
669                                                 ;Regs as for drEvent_draw
670                                                 ;Dash pattern set up so that
671                                                 ;single plot will rotate box,
672                                                 ;so may share code with
673                                                 ;drEvent_draw
674
675 drEvent_trans   #       1                       ;Translate coordinates
676                                                 ;R1 == ptr to window state
677                                                 ;R4,R5 == pointer position
678                                                 ;R6,R7 == window origin
679                                                 ;Translate pointer position
680                                                 ;to internal coordinates if
681                                                 ;this is useful to you.
682                                                 ;Return new coords in R4,R5
683
684 drEvent_getPos  #       1                       ;Read pointer position
685                                                 ;R1 == ptr to window state
686                                                 ;R2,R3 == start position
687                                                 ;R4,R5 == pointer position
688                                                 ;R6,R7 == window origin
689                                                 ;Used to read pointer posn.
690                                                 ;Do any grid snapping here
691                                                 ;and return with R4,R5 as
692                                                 ;coords to use.
693
694 drEvent_done    #       1                       ;Drag operation completed
695                                                 ;R1 == ptr to window state
696                                                 ;R2,R3 == drag start posn
697                                                 ;R4,R5 == drag current posn
698
699 drEvent_cancel  #       1                       ;Drag operation aborted
700                                                 ;No other registers set up
701
702 ;----- Workspace ------------------------------------------------------------
703
704                 ^       0,R12
705 drag__wStart    #       0
706
707 drag__window    #       4                       ;Window handle of drag
708 drag__flags     #       4                       ;Various interesting flags
709 drag__handler   #       16                      ;All the handler information
710 drag__oldDash   #       1                       ;The old dash pattern
711 drag__dash      #       1                       ;The current dash pattern
712                 #       2                       ;Align to word boundary
713 drag__lastTime  #       4                       ;Last time we changed pattern
714 drag__startPos  #       8                       ;Find the start position
715 drag__currPos   #       8                       ;Find the end position
716
717 drag__wSize     EQU     {VAR}-drag__wStart
718
719                 AREA    |Sapphire$$LibData|,CODE,READONLY
720
721                 DCD     drag__wSize
722                 DCD     drag__wSpace
723                 DCD     0
724                 DCD     0
725
726 ;----- That's all, folks ----------------------------------------------------
727
728                 END