Initial revision
[ssr] / StraySrc / Libraries / Sapphire / s / win
1 ;
2 ; win.s
3 ;
4 ; Window event dispatching (TMA)
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 ;----- External dependencies ------------------------------------------------
33
34 GET sapphire:sapphire
35 GET sapphire:suballoc
36 GET sapphire:event
37
38 ;----- Main code ------------------------------------------------------------
39
40 AREA |Sapphire$$Code|,CODE,READONLY
41
42 ; --- win__addToList ---
43 ;
44 ; On entry: R0 == window handle
45 ; R1 == pointer to routine to call
46 ; R2 == R10 value to call routine
47 ; R3 == R12 value to call routine with
48 ; R4 == pointer to list head to use
49 ;
50 ; On exit: R0-R4 preserved
51 ;
52 ; Use: Adds a rountine to the given list. Later added
53 ; routines are called first
54
55 win__addToList ROUT
56
57 STMFD R13!,{R0-R4,R14} ;Stack some registers
58
59 ; --- Allocate a block ---
60
61 MOV R0,#list__size ;Size to allocate
62 BL sub_alloc ;Allocate the block
63 BVS %01 ;Branch ahead if error
64
65 ; --- Fill the block in ---
66
67 LDR R1,[R4] ;Get the list head
68 STR R1,[R0,#list__next] ;Store in next field
69 STR R0,[R4] ;Store new block at head
70
71 LDMIA R13,{R1-R4} ;Get parameters
72 STMIB R0,{R1-R4} ;Store them in the block
73
74 ; --- And return to user ---
75
76 LDMFD R13!,{R0-R4,R14} ;Load back link
77 BICS PC,R14,#V_flag ;Return without error
78
79 ; --- Barf if an error occured ---
80
81 01 ADD R13,R13,#4 ;Skip over R0
82 LDMFD R13!,{R1-R4,R14} ;Branch if error
83 ORRS PC,R14,#V_flag ;Return with error
84
85 LTORG
86
87 ; --- win__removeFromList ---
88 ;
89 ; On entry: R0 == window handle
90 ; R1 == pointer to routine to called
91 ; R2 == R10 value routine is called with
92 ; R3 == R12 value routine is called with
93 ; R4 == pointer to list head to use
94 ;
95 ; On exit: All registers/flags preserved
96 ;
97 ; Use: Removes a routine from the given list. All values are
98 ; compared.
99
100 win__removeFromList
101 ROUT
102
103 STMFD R13!,{R0-R10,R12,R14}
104
105 ; --- Find the block ---
106
107 MOV R5,#0 ;The previous pointer
108 MOV R12,R4 ;Remember where the head is
109 LDR R4,[R4] ;Get the head of the list
110 01 TEQ R4,#0 ;Are we at the end?
111 LDMEQFD R13!,{R0-R10,R12,PC}^ ;Yes -- return
112 LDR R9,[R4],#4 ;Get the next pointer
113 LDMIA R4,{R6-R8,R10} ;Load data from the block
114 CMP R6,R0 ;Are handles/R4 the same?
115 CMPEQ R7,R1 ;Yes -- and routines to call?
116 CMPEQ R8,R2 ;Yes -- R10 value?
117 CMPEQ R10,R3 ;Yes -- R12 value?
118 SUBNE R5,R4,#4 ;If no, remember previous
119 MOVNE R4,R9 ;...get list pointer
120 BNE %01 ;...and keep looking
121
122 ; --- So now the block has been found ---
123
124 SUB R0,R4,#4 ;Put the block in R0
125 MOV R1,#list__size ;Get the size
126 BL sub_free ;Free the block
127 CMP R5,#0 ;Was there a previous block
128 STREQ R9,[R12,#0] ;No -- store next blk in head
129 STRNE R9,[R5,#0] ;Yes -- store in prev next ^
130
131 ; --- And return to the user ---
132
133 LDMFD R13!,{R0-R10,R12,PC}^
134
135 LTORG
136
137 ; --- win_eventHandler ---
138 ;
139 ; On entry: R0 == window handle
140 ; R1 == pointer to routine to call
141 ; R2 == R10 value to call routine with
142 ; R3 == R12 value to call routine with
143 ;
144 ; On exit: May return an error
145 ;
146 ; Use: Adds a routine to the event handler list. Later added
147 ; routines are called first. The event handing routine
148 ; must preserve all the registers, but may alter the carry
149 ; flag. If it returns with carry set, then no more event
150 ; handlers, OR post-filters, will be called.
151
152 EXPORT win_eventHandler
153 win_eventHandler
154 ROUT
155
156
157 STMFD R13!,{R4,R9,R14} ;Save some registers
158
159 ; --- Be careful not to alter flags ---
160
161 WSPACE win__wSpace,R9 ;Get my workspace pointer
162 ADR R4,win__eHandlers ;Get the event handlers
163 BL win__addToList ;Add the routine to the list
164 LDMFD R13!,{R4,R9,PC} ;Return cunningly
165
166 ; --- win_removeEventHandler ---
167 ;
168 ; On entry: R0 == window handle
169 ; R1 == pointer to routine called
170 ; R2 == R10 value routine is called with
171 ; R3 == R12 value routine is called with
172 ;
173 ; On exit: --
174 ;
175 ; Use: Removes a routine to the event handler list.
176
177 EXPORT win_removeEventHandler
178 win_removeEventHandler
179 ROUT
180
181 STMFD R13!,{R4,R9,R14} ;Stack some registers
182 WSPACE win__wSpace,R9 ;Get my workspace pointer
183 ADR R4,win__eHandlers ;Get the event handlers
184 BL win__removeFromList ;Remove routine from the list
185 LDMFD R13!,{R4,R9,PC}^ ;Load registers
186
187 LTORG
188
189 ; --- win_swapWindow ---
190 ;
191 ; On entry: R0 == old window handle
192 ; R1 == new window handle
193 ;
194 ; On exit: --
195 ;
196 ; Use: Searches for all the event handlers for window R0, and
197 ; changes the window handle for R1. This is designed for
198 ; situations in wihich a window has been deleted and
199 ; recreated.
200
201 EXPORT win_swapWindow
202 win_swapWindow ROUT
203
204 STMFD R13!,{R0-R3,R9,R14} ;Stack some registers
205 WSPACE win__wSpace,R9 ;Get my workspace pointer
206 LDR R2,win__eHandlers ;Get my event handlers list
207 10 TEQ R2,#0 ;Are we at the end
208 BEQ %20win_swapWindow ;Yes -- jump ahead
209 LDMIA R2,{R3,R14} ;Load some information
210 TEQ R14,R0 ;Are window handles the same
211 STREQ R1,[R2,#list__wHandle] ;Yes -- store new window hnd
212 MOV R2,R3 ;Put next handler in R2
213 B %10win_swapWindow ;Try another handler
214 20 LDMFD R13!,{R0-R3,R9,PC}^ ;Return to caller
215
216 LTORG
217
218 ; --- win_windowDeleted ---
219 ;
220 ; On entry: R0 == window handle
221 ;
222 ; On exit: --
223 ;
224 ; Use: Removes all the event handlers associated with the given
225 ; window handle. It is intended to be used when a window
226 ; has been deleted.
227
228 EXPORT win_windowDeleted
229 win_windowDeleted ROUT
230
231 STMFD R13!,{R0-R5,R9,R14} ;Stack some registers
232 WSPACE win__wSpace,R9 ;Get my workspace pointer
233
234 ; --- Find the block ---
235
236 MOV R5,#0 ;The previous pointer
237 LDR R2,win__eHandlers ;Get the event handlers
238 01 TEQ R2,#0 ;Are we at the end?
239 LDMEQFD R13!,{R0-R5,R9,PC}^ ;Yes -- return
240 LDMIA R2,{R3,R4} ;Get next/handle
241 CMP R4,R0 ;Are handles the same?
242 MOVNE R5,R2 ;If no, remember previous
243 MOVNE R2,R3 ;...get list pointer
244 BNE %01win_windowDeleted ;...and keep looking
245
246 ; --- So now the block has been found ---
247
248 MOV R0,R2 ;Put the block in R0
249 MOV R1,#list__size ;Get the size
250 BL sub_free ;Free the block
251 CMP R5,#0 ;Was there a previous block
252 ADREQ R14,win__eHandlers ;No -- point to list head
253 STREQ R3,[R14,#0] ;No -- store next blk in head
254 STRNE R3,[R5,#0] ;Yes -- store in prev next ^
255
256 ; --- Now search for the next one ---
257
258 MOV R2,R3 ;Put the next block in R2
259 B %01win_windowDeleted ;And keep on searching
260
261 LTORG
262
263 ; --- win_unknownHandler ---
264 ;
265 ; On entry: R0 == pointer to routine to call
266 ; R1 == R4 value to call routine with
267 ; R2 == R10 value to call routine with
268 ; R3 == R12 value to call routine with
269 ;
270 ; On exit: May return an error
271 ;
272 ; Use: Adds a rountine to the event handler list. Later added
273 ; routines are called first. The event handing routine
274 ; must preserve all the registers, but may alter the carry
275 ; flag. If it returns with carry set, then no more event
276 ; handlers, OR post-filters, will be called.
277
278 EXPORT win_unknownHandler
279 win_unknownHandler
280 ROUT
281
282
283 STMFD R13!,{R4,R9,R14} ;Save some registers
284
285 ; --- Be careful not to alter flags ---
286
287 WSPACE win__wSpace,R9 ;Get my workspace pointer
288 ADR R4,win__uHandlers ;Get the unknowns list
289 BL win__addToList ;Add the routine to the list
290 LDMFD R13!,{R4,R9,PC} ;Return cunningly
291
292 ; --- win_removeUnknownHandler ---
293 ;
294 ; On entry: R0 == pointer to routine called
295 ; R1 == R4 value routine is called with
296 ; R2 == R10 value routine is called with
297 ; R3 == R12 value routine is called with
298 ;
299 ; On exit: --
300 ;
301 ; Use: Removes a routine to the unknown handler list.
302
303 EXPORT win_removeUnknownHandler
304 win_removeUnknownHandler
305 ROUT
306
307 STMFD R13!,{R4,R9,R14} ;Stack some registers
308 WSPACE win__wSpace,R9 ;Get my workspace pointer
309 ADR R4,win__uHandlers ;Get the event handlers
310 BL win__removeFromList ;Remove routine from the list
311 LDMFD R13!,{R4,R9,PC}^ ;Load registers
312
313 LTORG
314
315 ; --- win__dispatchUnknown ---
316 ;
317 ; On entry: R0 == reason code returned from Wimp_Poll
318 ; R1 == pointer to block
319 ; R12 == pointer to workspace
320 ;
321 ; On exit: R0-R1 preserved
322 ; C Clear if the event is not claimed, Set otherwise
323
324 win__dispatchUnknown
325 ROUT
326
327 ; --- Note ---
328 ;
329 ; At this point, we've already got R2-R5, R9, R10, R12
330 ; and R14 on the stack.
331
332 ; --- Go through the handlers list ---
333
334 02 ADDS R0,R0,#0 ;Clear carry flag
335 LDR R2,win__uHandlers ;Get my event handlers list
336 10 TEQ R2,#0 ;Are we at the end
337 BEQ %20 ;Yes -- jump ahead
338 LDMIA R2,{R2-R4,R10,R12} ;Load parameters to pass
339 MOV R14,PC ;Set return address
340 MOV PC,R3 ;Branch to handler
341 BCC %10 ;Try next handler
342 20 LDMFD R13!,{R2-R5,R9,R10,R14} ;Load registers
343 ORRCSS PC,R14,#C_flag ;... and return
344 BICCCS PC,R14,#C_flag
345
346 LTORG
347
348 win__dispatchEvents
349 ROUT
350
351 STMFD R13!,{R2-R5,R9,R10,R14} ;Stack some registers
352 MOV R9,R12 ;Put my workspace in R9
353
354 ; --- Messages need special attention ---
355
356 CMP R0,#17 ;Is this User_Message?
357 CMPNE R0,#18 ;Or User_Message_Recorded?
358 BEQ %30 ;Yes -- off we go then
359
360 ; --- If it's some weird kind of message ---
361
362 CMP R0,#13 ;Highest event I know
363 BGT win__dispatchUnknown ;Too high -- unknown then
364
365 ; --- Find the table and get window handle offset ---
366
367 ADR R14,win__eventTbl ;Point to the table
368 LDRB R5,[R14,R0] ;Get offset for this event
369 CMP R5,#255 ;Is this event `unknown'?
370 BEQ win__dispatchUnknown ;Yes -- call unknown list
371 CMP R5,#254 ;Is it broadcastable?
372 LDRNE R5,[R1,R5] ;Get the window handle
373 MOVEQ R5,#&40000000 ;Or set up for broadcast
374
375 ; --- Go through the handlers list ---
376
377 05 ADDS R0,R0,#0 ;Clear carry flag
378 LDR R2,win__eHandlers ;Get my event handlers list
379 10 TEQ R2,#0 ;Are we at the end
380 BEQ %20 ;Yes -- jump ahead
381 LDMIA R2,{R2,R3,R4,R10,R12} ;Load parameters to pass
382 TEQ R5,R3 ;Are window handles the same
383 TEQNE R5,#&40000000 ;Or is this a broadcast?
384 BNE %10 ;No -- try another handler
385 MOV R14,PC ;Set return address
386 MOV PC,R4 ;Branch to handler
387 BCC %10 ;Try next handler
388 20 LDMFD R13!,{R2-R5,R9,R10,R14} ;Load the registers
389 BICCCS PC,R14,#C_flag ;Return with carry clear
390 ORRCSS PC,R14,#C_flag ;... or with carry set
391
392 ; --- Now try unknowns if I'm not claiming the message ---
393
394 30 LDR R2,[R1,#16] ;Get message code
395 ADR R14,win__msgTbl ;Point to message table
396 00 LDMIA R14!,{R3,R4} ;Load code and offset
397 CMP R2,R3 ;Does the code match?
398 LDREQ R5,[R1,R4] ;Yes -- load window handle
399 BEQ %05 ;And continue going
400 CMP R3,#-1 ;Is this the end yet?
401 BNE %b00 ;No -- keep going then
402
403 ; --- See if it's broadcastable ---
404
405 ADR R14,win__broadTbl ;Point to the table
406 00 LDR R3,[R14],#4 ;Load the message code
407 CMP R2,R3 ;Do we have a match?
408 MOVEQ R5,#&40000000 ;Yes -- signal broadcast
409 BEQ %05 ;And dispatch appropriately
410 CMP R3,#-1 ;Is this the end yet?
411 BNE %b00 ;No -- keep on going
412
413 B win__dispatchUnknown ;Unknown event -- dispatch it
414
415 DCB 0 ;Hint_Received
416 win__eventTbl DCB 255 ;Null
417 DCB 0 ;Redraw
418 DCB 0 ;Open
419 DCB 0 ;Close
420 DCB 0 ;Leave window
421 DCB 0 ;Enter window
422 DCB 12 ;Mouse click
423 DCB 255 ;Drag event
424 DCB 0 ;Key press
425 DCB 255 ;Menu choice
426 DCB 0 ;Scroll request
427 DCB 0 ;Lose caret
428 DCB 0 ;Gain caret
429 DCB 255 ;Poll word nonzero
430 ALIGN
431
432 win__msgTbl DCD &1, 20 ;DataSave
433 DCD &3, 20 ;DataLoad
434 DCD &502, 32 ;HelpRequest
435 DCD &11, 20 ;Dragging (drag'n'drop)
436 DCD -1, -1
437
438 win__broadTbl DCD &9 ;PaletteChange
439 DCD &400C1 ;ModeChange
440 DCD &400CF ;FontChange
441 DCD -1
442
443 LTORG
444
445 ; --- win_init ---
446 ;
447 ; On entry: --
448 ;
449 ; On exit: --
450 ;
451 ; Use: Initialises the win system.
452
453 EXPORT win_init
454 win_init ROUT
455
456 STMFD R13!,{R0,R1,R9,R14} ;Stack some registers
457 WSPACE win__wSpace,R9 ;Get my workspace
458
459 ; --- Are we already initialised? ---
460
461 LDR R0,win__flags ;Get my flags
462 TST R0,#win__INITED ;Are we initialised?
463 LDMNEFD R13!,{R0,R1,R9,PC}^ ;Yes -- return
464
465 ORR R0,R0,#win__INITED ;Set initialised flag
466 STR R0,win__flags ;And store them back
467
468 ; --- Clear rest of workspace ---
469
470 MOV R0,#0 ;Zero some registers
471 STR R0,win__eHandlers ;Clear event handlers list
472 STR R0,win__uHandlers ;Clear unknown list
473
474 ; --- Initialise event system ---
475
476 BL event_init ;Initialise event system
477
478 ; --- Set up a post filter for the win system ---
479
480 ADR R0,win__dispatchEvents ;Call this routine
481 MOV R1,R9 ;Put my workspace in R12
482 BL event_postFilter ;Add it to post-filter list
483
484 ; --- That's it now ---
485
486 LDMFD R13!,{R0,R1,R9,PC}^ ;Return
487
488 LTORG
489
490 win__wSpace DCD 0 ;My workspace pointer
491
492 ;----- Workspace ------------------------------------------------------------
493
494 ^ 0,R9
495 win__wStart # 0
496
497 win__flags # 4 ;Flags
498
499 win__INITED EQU (1<<0) ;I've been initialised
500
501 win__eHandlers # 4 ;Event handler list
502 win__uHandlers # 4 ;Unknown event handlers
503
504 win__wSize EQU {VAR}-win__wStart
505
506 ; --- list structure ---
507
508 ^ 0
509 list__next # 4 ;The next block
510 list__wHandle # 4 ;The window handle
511 list__proc # 4 ;Handler code
512 list__r10 # 4 ;R12 to call with
513 list__r12 # 4 ;R12 to call with
514
515 list__size # 0
516
517 AREA |Sapphire$$LibData|,CODE,READONLY
518
519 DCD win__wSize ;Workspace size
520 DCD win__wSpace ;Workspace pointer
521 DCD 0 ;Scratchpad size
522 DCD win_init ;Initialisation code
523
524 ;----- That's all, folks ----------------------------------------------------
525
526 END