4 ; Window event dispatching (TMA)
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 ------------------------------------------------------
32 ;----- External dependencies ------------------------------------------------
38 ;----- Main code ------------------------------------------------------------
40 AREA |Sapphire$$Code|,CODE,READONLY
42 ; --- win__addToList ---
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
50 ; On exit: R0-R4 preserved
52 ; Use: Adds a rountine to the given list. Later added
53 ; routines are called first
57 STMFD R13!,{R0-R4,R14} ;Stack some registers
59 ; --- Allocate a block ---
61 MOV R0,#list__size ;Size to allocate
62 BL sub_alloc ;Allocate the block
63 BVS %01 ;Branch ahead if error
65 ; --- Fill the block in ---
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
71 LDMIA R13,{R1-R4} ;Get parameters
72 STMIB R0,{R1-R4} ;Store them in the block
74 ; --- And return to user ---
76 LDMFD R13!,{R0-R4,R14} ;Load back link
77 BICS PC,R14,#V_flag ;Return without error
79 ; --- Barf if an error occured ---
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
87 ; --- win__removeFromList ---
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
95 ; On exit: All registers/flags preserved
97 ; Use: Removes a routine from the given list. All values are
103 STMFD R13!,{R0-R10,R12,R14}
105 ; --- Find the block ---
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
122 ; --- So now the block has been found ---
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 ^
131 ; --- And return to the user ---
133 LDMFD R13!,{R0-R10,R12,PC}^
137 ; --- win_eventHandler ---
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
144 ; On exit: May return an error
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.
152 EXPORT win_eventHandler
157 STMFD R13!,{R4,R9,R14} ;Save some registers
159 ; --- Be careful not to alter flags ---
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
166 ; --- win_removeEventHandler ---
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
175 ; Use: Removes a routine to the event handler list.
177 EXPORT win_removeEventHandler
178 win_removeEventHandler
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
189 ; --- win_swapWindow ---
191 ; On entry: R0 == old window handle
192 ; R1 == new window handle
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
201 EXPORT win_swapWindow
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
218 ; --- win_windowDeleted ---
220 ; On entry: R0 == window handle
224 ; Use: Removes all the event handlers associated with the given
225 ; window handle. It is intended to be used when a window
228 EXPORT win_windowDeleted
229 win_windowDeleted ROUT
231 STMFD R13!,{R0-R5,R9,R14} ;Stack some registers
232 WSPACE win__wSpace,R9 ;Get my workspace pointer
234 ; --- Find the block ---
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
246 ; --- So now the block has been found ---
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 ^
256 ; --- Now search for the next one ---
258 MOV R2,R3 ;Put the next block in R2
259 B %01win_windowDeleted ;And keep on searching
263 ; --- win_unknownHandler ---
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
270 ; On exit: May return an error
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.
278 EXPORT win_unknownHandler
283 STMFD R13!,{R4,R9,R14} ;Save some registers
285 ; --- Be careful not to alter flags ---
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
292 ; --- win_removeUnknownHandler ---
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
301 ; Use: Removes a routine to the unknown handler list.
303 EXPORT win_removeUnknownHandler
304 win_removeUnknownHandler
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
315 ; --- win__dispatchUnknown ---
317 ; On entry: R0 == reason code returned from Wimp_Poll
318 ; R1 == pointer to block
319 ; R12 == pointer to workspace
321 ; On exit: R0-R1 preserved
322 ; C Clear if the event is not claimed, Set otherwise
329 ; At this point, we've already got R2-R5, R9, R10, R12
330 ; and R14 on the stack.
332 ; --- Go through the handlers list ---
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
351 STMFD R13!,{R2-R5,R9,R10,R14} ;Stack some registers
352 MOV R9,R12 ;Put my workspace in R9
354 ; --- Messages need special attention ---
356 CMP R0,#17 ;Is this User_Message?
357 CMPNE R0,#18 ;Or User_Message_Recorded?
358 BEQ %30 ;Yes -- off we go then
360 ; --- If it's some weird kind of message ---
362 CMP R0,#13 ;Highest event I know
363 BGT win__dispatchUnknown ;Too high -- unknown then
365 ; --- Find the table and get window handle offset ---
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
375 ; --- Go through the handlers list ---
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
392 ; --- Now try unknowns if I'm not claiming the message ---
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
403 ; --- See if it's broadcastable ---
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
413 B win__dispatchUnknown ;Unknown event -- dispatch it
416 win__eventTbl DCB 255 ;Null
426 DCB 0 ;Scroll request
429 DCB 255 ;Poll word nonzero
432 win__msgTbl DCD &1, 20 ;DataSave
434 DCD &502, 32 ;HelpRequest
435 DCD &11, 20 ;Dragging (drag'n'drop)
438 win__broadTbl DCD &9 ;PaletteChange
439 DCD &400C1 ;ModeChange
440 DCD &400CF ;FontChange
451 ; Use: Initialises the win system.
456 STMFD R13!,{R0,R1,R9,R14} ;Stack some registers
457 WSPACE win__wSpace,R9 ;Get my workspace
459 ; --- Are we already initialised? ---
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
465 ORR R0,R0,#win__INITED ;Set initialised flag
466 STR R0,win__flags ;And store them back
468 ; --- Clear rest of workspace ---
470 MOV R0,#0 ;Zero some registers
471 STR R0,win__eHandlers ;Clear event handlers list
472 STR R0,win__uHandlers ;Clear unknown list
474 ; --- Initialise event system ---
476 BL event_init ;Initialise event system
478 ; --- Set up a post filter for the win system ---
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
484 ; --- That's it now ---
486 LDMFD R13!,{R0,R1,R9,PC}^ ;Return
490 win__wSpace DCD 0 ;My workspace pointer
492 ;----- Workspace ------------------------------------------------------------
497 win__flags # 4 ;Flags
499 win__INITED EQU (1<<0) ;I've been initialised
501 win__eHandlers # 4 ;Event handler list
502 win__uHandlers # 4 ;Unknown event handlers
504 win__wSize EQU {VAR}-win__wStart
506 ; --- list structure ---
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
517 AREA |Sapphire$$LibData|,CODE,READONLY
519 DCD win__wSize ;Workspace size
520 DCD win__wSpace ;Workspace pointer
521 DCD 0 ;Scratchpad size
522 DCD win_init ;Initialisation code
524 ;----- That's all, folks ----------------------------------------------------