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