4 ; Handles things that should auto-repeat
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 ------------------------------------------------
41 ;----- Main code ------------------------------------------------------------
43 AREA |Sapphire$$Code|,CODE,READONLY
47 ; On entry: R0 == pointer to routine to call
48 ; R1 == R10 value to pass to routine
49 ; R2 == R12 value to pass to routine
53 ; Use: Calls a routine (a) immediately, (b) after the configured
54 ; keyboard delay rate and (c) repeatedly after the configured
55 ; keyboard repeat rate. Calls stop when the user stops
56 ; pressing the mouse button.
58 ; The routine is called with R0 containing either the number
59 ; of missed calls since the last one (normally this is 1) --
60 ; this is intended to be used to implement a kind of buffering
61 ; of repeats if the operation being performed is a lengthy one
62 ; -- and with 0 to indicate that the operation is now
68 STMFD R13!,{R0-R4,R12,R14} ;Save some registers
69 WSPACE rpt__wSpace ;Locate my workspace nicely
71 ; --- Set up the workspace ---
73 STMIA R12,{R0-R2} ;Save the call information
74 MOV R0,#1 ;This is the first call
75 BL rpt__call ;Call the user's routine
77 ; --- Now we have to work out the repeat times ---
79 MOV R0,#196 ;Read keybd repeat and delay
80 MOV R1,#0 ;Set up registers to read...
81 MOV R2,#255 ;... without corrupting
82 SWI OS_Byte ;Read the autorepeat info
83 STR R2,rpt__repeat ;Save repeat rate in wspace
84 MOVS R4,R1 ;Look after delay time
86 MOVEQ R0,#0 ;If no delay, end op now
87 BLEQ rpt__call ;Tell client it's over
88 BEQ %90repeater ;And exit nicely
90 ; --- Set up the drag box ---
92 ; We do this for several reasons:
94 ; * It informs us when the mouse button is finally released.
96 ; * It keeps the mouse pointer bounded for the duration.
98 ; * It stops things going wrong if for some reason the mouse
99 ; gets unbounded (e.g. by doing a Wimp_SetMode).
101 SUB R13,R13,#56 ;Get a drag box block
102 MOV R1,R13 ;Point to the block
103 SWI Wimp_GetPointerInfo ;Get the current mouse state
104 LDMIA R13,{R2,R3} ;Read mouse position
105 MOV R1,#7 ;This drag is a user type
106 STMIA R13,{R0,R1} ;Save them in the block
107 ADD R14,R13,#24 ;Point to parent rectangle
108 STMIA R14!,{R2,R3} ;Save the current mouse...
109 STMIA R14!,{R2,R3} ;... posn to lock in place
110 MOV R1,R13 ;Point to the block
111 SWI Wimp_DragBox ;Start the drag operation
112 ADD R13,R13,#56 ;Restore the stack now
114 ; --- Now set up the unknown handler to catch the drag ---
116 ADR R0,rpt__ukEvents ;Point to my handler routine
117 MOV R1,#0 ;Don't care about R4
118 MOV R2,#0 ;Nothing to pass in R10
119 MOV R3,R12 ;Pass workspace in R12
120 BL win_unknownHandler ;Add the handler
121 BVS %90repeater ;If it failed, skip to end
123 ; --- Set up the alarm for the first repeat ---
125 SWI OS_ReadMonotonicTime ;Read the current time
126 ADD R0,R4,R0 ;Add time to keyboard delay
127 STR R0,rpt__alarm ;Store the time of the alarm
128 STR R0,rpt__last ;And this is correct time
129 ADR R1,rpt__alarms ;Point to my alarm handler
130 MOV R2,#0 ;Nothing to pass in R10
131 MOV R3,R12 ;Pass workspace in R12
132 BL idle_setAlarm ;Set the alarm call then
134 90repeater LDMFD R13!,{R0-R4,R12,PC}^ ;Return to caller if all OK
140 ; On entry: R0 == value to pass client in R0
144 ; Use: Calls client routine.
148 STMFD R13!,{R1,R10,R12,R14} ;Save some registers
149 LDMIA R12,{R1,R10,R12} ;Load client's routine data
150 MOV R14,PC ;Set up return address
151 MOV PC,R1 ;And call the routine
152 LDMFD R13!,{R1,R10,R12,PC}^ ;And return to caller
156 ; --- rpt__alarms ---
162 ; Use: Handles alarms while a repeater is in operation.
166 STMFD R13!,{R0-R4,R14} ;Save some registers
168 LDR R0,rpt__routine ;Load the current addr
169 CMP R0,#-1 ;Have we ended?
170 BEQ %70rpt__alarms ;Yes -- do special things
172 ; --- Things go odd if zero repeat rate set up ---
174 LDR R2,rpt__repeat ;Load current repeat rate
175 CMP R2,#0 ;Is it currently zero?
176 BEQ %50rpt__alarms ;Yes -- handle specially
178 ; --- Work out how many we missed ---
180 ; We also add in the next alarm, and resynch to the
183 SWI OS_ReadMonotonicTime ;Get the current time
184 MOV R4,R0 ;Look after this value
185 LDR R3,rpt__last ;Get the time I was expecting
186 SUB R0,R4,R3 ;Find how late I was called
187 MOV R1,R2 ;Get the repeat rate ready
188 BL divide ;Find out how many I missed
189 ADD R0,R0,#1 ;Add in one extra repeat
190 BL rpt__call ;Call client code again
191 SUB R14,R2,R1 ;Work out next repeat time
192 ADD R0,R4,R14 ;Add that to current time
193 STR R0,rpt__last ;This is the new alarm time
195 SWI OS_ReadMonotonicTime ;Get the current time
196 MOV R4,R0 ;Look after this now
197 SUB R0,R4,R3 ;Find how late I was called
198 MOV R1,R2 ;Get the repeat rate ready
199 BL divide ;Find out how many I missed
200 SUB R14,R2,R1 ;Work out next repeat time
201 ADD R0,R4,R14 ;Add that to current time
202 STR R0,rpt__alarm ;This is the new alarm time
204 ADR R1,rpt__alarms ;Point to me again
205 MOV R2,R10 ;Pass the dialogue handle
206 MOV R3,R12 ;And my workspace pointer
207 BL idle_setAlarm ;Add in next alarm handler
209 LDMFD R13!,{R0-R4,PC}^ ;And return to caller
211 ; --- If no repeat rate, stop the whole operation ---
213 50rpt__alarms MOV R0,#1 ;Just send one call
214 BL rpt__call ;Send that off to the client
215 MOV R1,#-1 ;Tell Wimp to stop dragging
216 SWI Wimp_DragBox ;Send that off nicely
217 ADR R0,rpt__ukEvents ;Point to the unknown handler
218 MOV R1,#0 ;I'm passing 0 in R4
219 MOV R2,#0 ;And 0 in R10 too
220 MOV R3,R12 ;But R12 is my workspace
221 BL win_removeUnknownHandler ;Remove it from the list
222 MOV R0,#0 ;Tell client it's all over
223 BL rpt__call ;Finish that off nicely
224 LDMFD R13!,{R0-R4,PC}^ ;And return to caller
226 ; --- The repeater was ended before its time ---
228 70rpt__alarms MOV R1,#-1 ;Tell Wimp to stop dragging
229 SWI Wimp_DragBox ;Send that off nicely
230 ADR R0,rpt__ukEvents ;Point to the unknown handler
231 MOV R1,#0 ;I'm passing 0 in R4
232 MOV R2,#0 ;And 0 in R10 too
233 MOV R3,R12 ;But R12 is my workspace
234 BL win_removeUnknownHandler ;Remove it from the list
235 LDMFD R13!,{R0-R4,PC}^ ;And return to caller
245 ; Use: Ends a repeater before the drag is released. No final
246 ; 0 is sent to the handler.
251 STMFD R13!,{R12,R14} ;Stack registers
252 WSPACE rpt__wSpace ;Locate my workspace nicely
253 MOV R14,#-1 ;Get a silly routine value
254 STR R14,rpt__routine ;Store in routine address
255 LDMFD R13!,{R12,PC}^ ;Return to caller
259 ; --- rpt__ukEvents ---
261 ; On entry: R0 == event code
262 ; R1 == pointer to event information
266 ; Use: Picks up end-of-drag events from the WindowMangler and
267 ; diables the alarm for the repeat op.
271 CMP R0,#7 ;Is this a drag event?
272 MOVNES PC,R14 ;No -- return right away
273 STMFD R13!,{R0-R3,R14} ;Save some registers away
275 ; --- Remove the alarm and unknown handlers ---
277 LDR R0,rpt__alarm ;Get the time it's due for
278 ADR R1,rpt__alarms ;Point to my alarms routine
279 MOV R2,#0 ;I passed 0 as it's R10
280 MOV R3,R12 ;Get its R12 value
281 BL idle_removeAlarm ;And remove it from the list
282 ADR R0,rpt__ukEvents ;Point to the unknown handler
283 MOV R1,#0 ;I'm passing 0 in R4
284 BL win_removeUnknownHandler ;Remove it from the list
286 ; --- Tell the client it's over ---
288 MOV R0,#0 ;Say this is it then
289 BL rpt__call ;Send the event over
290 LDMFD R13!,{R0-R3,PC}^ ;Return to caller
296 ;----- Workspace ------------------------------------------------------------
301 rpt__routine # 4 ;Client routine to call
302 rpt__R10 # 4 ;R10 value to pass routine
303 rpt__R12 # 4 ;R12 value to pass routine
304 rpt__repeat # 4 ;Current autorepeat rate
305 rpt__alarm # 4 ;Time for next alarm pop
306 rpt__last # 4 ;When last pop expected
308 rpt__wSize EQU {VAR}-rpt__wStart
310 AREA |Sapphire$$LibData|,CODE,READONLY
317 ;----- That's all, folks ----------------------------------------------------