Initial revision
[ssr] / StraySrc / Libraries / Sapphire / s / listbox
1 ;
2 ; listbox.s
3 ;
4 ; Nice listbox handling routines (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:alloc
35 GET sapphire:fastMove
36 GET sapphire:idle
37 GET sapphire:divide
38 GET sapphire:pane
39 GET sapphire:resspr
40 GET sapphire:sapphire
41 GET sapphire:screen
42 GET sapphire:tspr
43 GET sapphire:win
44
45 ;----- Main code ------------------------------------------------------------
46
47 AREA |Sapphire$$Code|,CODE,READONLY
48
49 ; --- lb_create ---
50 ;
51 ; On entry: R0 == pointer to list manager description block
52 ; R1 == pointer to the list
53 ; R2 == pointer to a width function
54 ; R3 == The height of each item
55 ; R4 == parent window handle or
56 ; pointer to window block if R5 == -1
57 ; R5 == parent icon handle or -1 if not a pane
58 ;
59 ; On exit: R0 == listbox handle
60 ; R1 == window handle of list box
61 ; May return an error (R1 corrupted)
62
63 EXPORT lb_create
64 lb_create ROUT
65
66 STMFD R13!,{R2,R3,R10,R14} ;Stack some registers
67
68 ; --- First, create the block ---
69
70 MOV R10,R0 ;Preserve R0
71 MOV R0,#lb__size ;The structure size
72 BL alloc ;Get the block
73 BLCS alloc_error ;Get a message if no memory
74 BCS %99lb_create ;Return on error
75
76 MOV R14,R10 ;Do a swap type thing
77 MOV R10,R0 ;Point to the block
78 MOV R0,R14 ;Confused yet?
79 STMIA R10,{R0-R5} ;Store information in block
80 MOV R0,#0 ;No flags set yet
81 STR R0,[R10,#lb__flags] ;Store this word
82 STR R0,[R10,#lb__handler] ;No handler either
83 BL lb__getMaxWidth ;Find length of longest item
84
85 ; --- Calculate the minimum width and height of the box ---
86
87 CMP R5,#-1 ;Is this a pane listbox?
88 BNE %10lb_create ;No -- use icon then
89
90 MOV R14,#176 ;A minimum height
91 STR R14,[R10,#lb__height] ;Store the width
92 LDR R0,[R4,#0] ;Load the minimum x position
93 LDR R14,[R4,#8] ;Load the maximum x position
94 SUB R0,R14,R0 ;Get the initial width
95 STR R0,[R10,#lb__width] ;Store the width
96 B %20lb_create ;And jump ahead a bit
97
98 10lb_create SUB R13,R13,#40 ;Get another block
99 STR R4,[R13,#0] ;Store parent window handle
100 STR R5,[R13,#4] ;And icon handle
101 MOV R1,R13 ;Point to the block
102 SWI Wimp_GetIconState ;Get the icon's state
103
104 LDR R2,[R1,#16] ;Get the x1 coord
105 LDR R14,[R1,#8] ;And x0 coord
106 SUB R2,R2,R14 ;Calculate the icon width
107 STR R2,[R10,#lb__width] ;Store the width
108 LDR R2,[R1,#20] ;Get the y1 coord
109 LDR R14,[R1,#12] ;And y0 coord
110 SUB R2,R2,R14 ;Calculate the icon height
111 STR R2,[R10,#lb__height] ;Store the height
112 ADD R13,R13,#40 ;Get the block back
113
114 ; --- Now create the window ---
115
116 20lb_create SUB R13,R13,#88 ;Get a block
117 MOV R0,R13 ;Point to it
118 CMP R5,#-1 ;Is this a pane listbox?
119 ADRNE R1,lb__windowDef ;No -- point to my window def
120 MOVEQ R1,R4 ;Yes -- use theirs then
121 MOV R2,#lb__defSize ;Copy this much
122 BL fastMove ;Copy the definition across
123 LDR R1,[R10,#lb__height] ;y0
124 RSB R1,R1,#0 ;Negate it
125 LDR R2,[R10,#lb__width] ;x1
126 ADD R14,R13,#44 ;The workarea extent block
127 STMIA R14,{R1,R2} ;Store the desired extent
128 BL resspr_area ;Find the sprite area
129 STR R0,[R13,#64] ;Store this in the block
130 MOV R1,R13 ;Point to the block
131 SWI Wimp_CreateWindow ;Try to create the window
132 ADD R13,R13,#88 ;Get the stack back
133 BVS %98lb_create ;Return on error
134 STR R0,[R10,#lb__wHandle] ;Store my window handle
135
136 ; --- Set up the event handler ---
137
138 ADR R1,lb__eventHandler ;Point to the event handler
139 MOV R2,R10 ;R10 value to call with
140 MOV R3,#0 ;R12 value to call with
141 BL win_eventHandler ;Add in the event handler
142
143 ; --- Add it as a pane to the parent (if we need to) ---
144
145 MOV R2,R0 ;The window handle
146 MOV R0,R4 ;Parent window handle
147 MOVS R1,R5 ;Parent icon handle
148 BLPL pane_add ;Register the pane (if reqd)
149
150 ; --- Add scroll bars if we need too ---
151
152 ORR R10,R10,#(1<<31) ;Don't open the window
153 BL lb__rescanSize ;Re-scan the size nicely
154 BIC R10,R10,#(1<<31) ;Clear silly bit again
155 BVS %98lb_create ;Return om error
156
157 LDR R1,[R10,#lb__wHandle] ;Return window handle in R1
158 MOV R0,R10 ;Return the listbox handle
159 B %99lb_create ;Return to caller
160
161 98lb_create MOV R0,R10 ;Point to the allocated block
162 BL free ;Free the block
163 99lb_create LDMFD R13!,{R2,R3,R10,R14} ;Get registers back
164 ORRVSS PC,R14,#V_flag ;And return either with...
165 BICVCS PC,R14,#V_flag ;...or without error
166
167 LTORG
168
169 lb__windowDef DCD 320,256,960,768
170 DCD 0,0
171 DCD -1
172 DCD &80000122
173 DCB 7,2,7,255,3,1,12,0
174 DCD 0,0,0,0
175 DCD &39,10<<12
176 DCD 0,0
177 DCB "ListBox",0,0
178 DCD 0
179
180 lb__defSize EQU {PC}-lb__windowDef
181
182 ; --- lb__rescanSize ---
183 ;
184 ; On entry: R10 == pointer to listbox
185 ; Bit 31 == don't call open the window
186 ;
187 ; On exit: VS and R0 == pointer to error or
188 ; VC and R0 == window handle
189 ;
190 ; Use: Scans the list, and adds/removes scroll bars if necessary
191
192 lb__rescanSize ROUT
193
194 STMFD R13!,{R1-R10,R14} ;Stack some registers
195 BIC R10,R10,#(1<<31) ;Clear the top bit
196
197 ; --- First get the window state of the current window ---
198
199 SUB R13,R13,#36 ;Get a block
200 LDR R0,[R10,#lb__wHandle] ;Get the window handle
201 STR R0,[R13,#0] ;Store in the block
202 MOV R1,R13 ;Point to the block
203 SWI Wimp_GetWindowState ;Get the window state
204 LDR R6,[R1,#32] ;Get the window flags
205 ADD R13,R13,#36 ;Get the block back again
206 LDR R9,[R10,#lb__descriptor] ;Point to descriptor block
207 LDR R0,[R10,#lb__list] ;Point to the list itself
208 MOV R14,PC ;Set up the return address
209 ADD PC,R9,#lb_items ;Call the function
210 LDR R7,[R10,#lb__iHeight] ;The height of each item
211 MUL R7,R1,R7 ;The required box y extent
212 LDR R4,[R10,#lb__width] ;Overall box width
213 LDR R5,[R10,#lb__height] ;Overall box height
214 BL tspr_borderWidths ;Get the border widths
215 BL screen_getInfo ;Get pixel sizes
216 LDR R14,[R0,#screen_dx] ;x pixel size
217 SUB R4,R4,R14,LSL#1 ;Correct overall width
218 ADD R1,R1,R14 ;Set up border width
219 LDR R14,[R0,#screen_dy] ;y pixel size
220 SUB R5,R5,R14,LSL#1 ;Correct overall height
221 SUB R2,R2,R14 ;Set up border height
222 LDR R14,[R10,#lb__pIHandle] ;Get the parent icon handle
223 CMP R14,#-1 ;Is this a pane dialogue?
224 BEQ %50lb__rescanSize ;Yes -- jump ahead then
225
226 ; --- Which scroll bars do we want? ---
227
228 MOV R14,#0 ;No flags so far
229 LDR R0,[R10,#lb__maxWidth] ;Get the width required
230 CMP R0,R4 ;Is width>overall?
231 ORRGT R14,R14,#(1<<30) ;Yes -- we need horz. scr bar
232 SUBGT R5,R5,R2 ;Reduce overall height
233
234 CMP R7,R5 ;Do we need a vertical bar?
235 ORRGT R14,R14,#(1<<28) ;Yes -- make a note of this
236 SUBGT R4,R4,R1 ;Reduce overall width
237
238 TST R14,#(1<<30) ;Do we have a horz. bar?
239 BNE %00lb__rescanSize ;Yes -- jump ahead
240 CMP R0,R4 ;Is width>overall?
241 ORRGT R14,R14,#(1<<30) ;Yes -- we need horz. scr bar
242 SUBGT R5,R5,R2 ;Reduce overall height
243
244 ; --- Do we need to add/remove scroll bars? ---
245
246 00 AND R0,R6,#&50000000 ;The scroll bars we have
247 CMP R0,R14 ;Are the flags the same
248 BEQ %50lb__rescanSize ;Yes -- jump ahead
249
250 ; --- Now we need to recreate the window ---
251
252 BIC R6,R6,#&50000000 ;No scroll bars at all
253 ORR R6,R6,R14 ;Just the ones we want please
254
255 ; --- Now create the new window ---
256
257 SUB R13,R13,#88 ;Get a block
258 MOV R0,R13 ;Point to it
259 ADR R1,lb__windowDef ;Point to window definition
260 MOV R2,#lb__defSize ;Copy this much
261 BL fastMove ;Copy the definition across
262 RSB R1,R7,#0 ;y0
263 LDR R2,[R10,#lb__maxWidth] ;x1
264 ADD R14,R13,#44 ;The workarea extent block
265 STMIA R14,{R1,R2} ;Store the desired extent
266 STR R6,[R13,#28] ;Store the flags word
267 BL resspr_area ;Find the sprite area
268 STR R0,[R13,#64] ;Store this in the block
269 MOV R1,R13 ;Point to the block
270 SWI Wimp_CreateWindow ;Try to create the window
271 ADD R13,R13,#88 ;Get the block back
272 LDRVS R0,[R10,#lb__pWHandle] ;On error, get window handle
273 LDRVS R1,[R10,#lb__pIHandle] ;...get the icon handle
274 BLVS pane_remove ;...remove the pane
275 BVS %99lb__rescanSize ;...and Barf with error
276
277 MOV R1,R0 ;Look after the window handle
278 LDR R0,[R10,#lb__wHandle] ;Load the old handle
279 BL win_swapWindow ;Tell win the handle changed
280 MOV R2,R1 ;Look after new handle
281 ADD R1,R10,#lb__wHandle ;Point to the old handle
282 SWI Wimp_DeleteWindow ;Destroy the old window
283 STR R2,[R10,#lb__wHandle] ;Store the new window handle
284
285 LDR R0,[R10,#lb__pWHandle] ;Parent window handle
286 LDR R1,[R10,#lb__pIHandle] ;Parent icon handle
287 BL pane_swap ;Swap the pane
288 B %50lb__rescanSize ;Jump ahead a little
289
290 50 ; --- Work out the correct extents ---
291
292 BL screen_getInfo ;Get pixel sizes
293 LDR R14,[R0,#screen_dx] ;x pixel size
294 ADD R4,R4,R14,LSL#1 ;Correct overall width
295
296 CMP R7,R5 ;Is required<overall height?
297 MOVLT R7,R5 ;Yes -- make them the same
298 LDR R3,[R10,#lb__maxWidth] ;Get the width required
299 CMP R3,R4 ;Is required<overall width?
300 MOVLT R3,R4 ;Yes -- make them the same
301 SUB R13,R13,#16 ;Get a small block
302 MOV R1,#0 ;x0 extent
303 RSB R2,R7,#0 ;y0 extent
304 MOV R4,#0 ;y1 extent
305 STMIA R13,{R1-R4} ;Store the required extent
306 MOV R1,R13 ;Point to the block
307 LDR R5,[R10,#lb__wHandle] ;Load the window handle
308 MOV R0,R5 ;Put it in R0
309 SWI Wimp_SetExtent ;Set the window extent
310 ADD R13,R13,#16 ;Reclaim the block again
311
312 LDR R14,[R13,#36] ;Load R10 value
313 TST R14,#(1<<31) ;Should we return here
314 BNE %90lb__rescanSize ;Yes -- return then
315 LDR R14,[R10,#lb__pIHandle] ;Get the parent icon
316 CMP R14,#-1 ;Is the listbox attached?
317 STREQ R5,[R13,#-36]! ;Yes -- store window handle
318 MOVEQ R1,R13 ;Point at the block
319 SWIEQ Wimp_GetWindowState ;Find the current position
320 SWIEQ Wimp_OpenWindow ;And open it again
321 ADDEQ R13,R13,#36 ;Restore the stack
322 LDRNE R0,[R10,#lb__pWHandle] ;Parent window handle
323 BLNE pane_open ;Open the listbox cunningly
324 90 MOV R0,R5 ;Get the window handle back
325
326 ; --- Return to caller ---
327
328 99 LDMFD R13!,{R1-R10,R14} ;Load registers
329 ORRVSS PC,R14,#V_flag ;And return with...
330 BICVCS PC,R14,#V_flag ;...or without error
331
332 LTORG
333
334 ; --- lb_destroy ---
335 ;
336 ; On entry: R0 == listbox handle
337 ;
338 ; On exit: --
339 ;
340 ; Use: Destroys the given listbox.
341
342 EXPORT lb_destroy
343 lb_destroy ROUT
344
345 STMFD R13!,{R0-R3,R10,R14} ;Stack some registers
346 MOV R10,R0 ;Keep the pointer
347 ADD R1,R10,#lb__wHandle ;Point to the window handle
348 SWI XWimp_CloseWindow ;Close the window
349 SWI Wimp_DeleteWindow ;And the delete it
350
351 ; --- Remove the pane attachment ---
352
353 LDR R0,[R10,#lb__pWHandle] ;Get the parent window handle
354 LDR R1,[R10,#lb__wHandle] ;Get the listbox window hnd
355 BL pane_remove ;Remove the pane
356
357 ; --- Remove the event handler ---
358
359 MOV R0,R1 ;The window handle
360 BL win_windowDeleted ;Remove the handler
361
362 ; --- Finally, free the block ---
363
364 MOV R0,R10 ;Point to the block
365 BL free ;Free it
366
367 LDMFD R13!,{R0-R3,R10,PC}^ ;Return to caller
368
369 ; --- lb_eventHandler ---
370 ;
371 ; On entry: R0 == listbox handle
372 ; R1 == handler function
373 ; R2 == R10 value to pass
374 ; R3 == R12 value to pass
375 ;
376 ; On exit: --
377 ;
378 ; Use: Registers an event handler for the given listbox.
379
380 EXPORT lb_eventHandler
381 lb_eventHandler ROUT
382
383 STMFD R13!,{R14} ;Stack some registers
384 ADD R14,R0,#lb__handler ;Point to nice block
385 STMIA R14,{R1-R3} ;Store the information
386 LDMFD R13!,{PC}^ ;Return to caller
387
388 LTORG
389
390 ; --- lb__getMaxWidth ---
391 ;
392 ; On entry: R10 == pointer to listbox structure
393 ;
394 ; On exit: R0 == longest item width in the list
395
396 lb__getMaxWidth ROUT
397
398 STMFD R13!,{R1-R7,R14} ;Stack some registers
399
400 MOV R4,#0 ;The longest width so far
401 LDR R5,[R10,#lb__widthFun] ;Get the width function ptr
402 LDR R6,[R10,#lb__descriptor] ;Point to the descriptor blk
403 LDR R0,[R10,#lb__list] ;Get the list head
404 MOV R1,#0 ;From the first item
405 MOV R2,#0 ;No mask word
406 MOV R3,#0 ;Or test word
407 00 MOV R14,PC ;Set up the return address
408 ADD PC,R6,#lb_enumerate ;Get a list item
409 BCC %99lb__getMaxWidth ;No more items -- return
410 MOV R7,R1 ;Remember the R1 value
411 MOV R14,PC ;Set up return address
412 MOV PC,R5 ;Call the width function
413 CMP R1,R4 ;Is the the longest width?
414 MOVGT R4,R1 ;Yes -- remember this fact
415 MOV R1,R7 ;Put R1 back again
416 B %00lb__getMaxWidth ;Check other items
417
418 99 MOV R0,R4 ;Put width in R0
419 STR R0,[R10,#lb__maxWidth] ;And store in the listbox
420 LDMFD R13!,{R1-R7,PC}^ ;And return to caller
421
422 LTORG
423
424 ; --- lb__eventHandler ---
425 ;
426 ; On entry: R0 == event type
427 ; R1 == pointer to event block
428 ;
429 ; On exit: --
430 ;
431 ; Use: Called to deal with events on the listbox window
432
433 lb__eventHandler ROUT
434
435 CMP R0,#1 ;Is it a redraw event?
436 BEQ lb__redraw ;Yes -- handle it then
437 CMP R0,#3 ;Is it a close event?
438 BEQ lb__close ;Yes -- report it then
439 CMP R0,#10 ;Scroll request?
440 BEQ lb__scroll ;Yes -- let's hope we cope
441 CMP R0,#6 ;Is it a click event?
442 BEQ lb__click ;Yes -- handle that
443 CMP R0,#17 ;Is it a message (normal)?
444 CMPNE R0,#18 ;Or a rubber message?
445 BEQ lb__message ;Yes -- handle it then
446
447 BICS PC,R14,#C_flag ;Return -- didn't understand
448
449 LTORG
450
451 ; --- lb__dispatch ---
452 ;
453 ; On entry: R0 == a list box event code
454 ; R1-R8 == arguments for the client's event handler
455 ; R10 == list box handle
456 ;
457 ; On exit: CC or CS, from the event handler
458 ;
459 ; Use: Sends an event to the user event handler for the list box.
460
461 lb__dispatch ROUT
462
463 STMFD R13!,{R9,R10,R12,R14} ;Save some useful registers
464 ADD R14,R10,#lb__handler ;Point to the handler stuff
465 LDMIA R14,{R9,R10,R12} ;Load the appropriate bits
466 ADDS R0,R0,#0 ;Clear the carry flag
467 TEQ R9,#0 ;Is there a handler defined?
468 MOV R14,PC ;Set up a return address
469 MOVNE PC,R9 ;Yes -- call the handler
470 LDMFD R13!,{R9,R10,R12,R14} ;Unstack the registers again
471 BICCCS PC,R14,#C_flag ;If C clear then clear C
472 ORRCSS PC,R14,#C_flag ;If C set then set C
473
474 LTORG
475
476 ; --- lb__message ---
477 ;
478 ; On entry: R0 == message type (17 or 18)
479 ; R1 == event block
480 ;
481 ; On exit: --
482 ;
483 ; Use: Called when the listbox recieves a message
484
485 lb__message ROUT
486
487 STMFD R13!,{R0-R5,R14} ;Stack some messages
488 LDR R0,[R1,#16] ;Get the message type
489 CMP R0,#1 ;Is it a save message?
490 CMPNE R0,#3 ;Or a load message?
491 BEQ %10lb__message ;Yes -- handle them the same
492 LDR R14,=&502 ;The help message code
493 CMP R0,R14 ;Is that the message?
494 BEQ %05lb__message ;Yes -- deal with it
495
496 ; --- Check for mode/font changes ---
497
498 CMP R0,R14 ;Are they the same
499 LDRNE R14,=&400CF ;Also get a FontChange msg
500 CMPNE R0,R14 ;Does this match?
501 BLEQ lb__getMaxWidth ;Yes -- calculate max width
502 BLEQ lb__rescanSize ;...and rescan the size
503 LDMFD R13!,{R0-R5,PC}^ ;And return to caller
504
505 ; --- Handle a help request ---
506
507 05lb__message ADD R1,R1,#20 ;Point to mouse info
508 BL lb__getItem ;Get the item under pointer
509 MOV R0,#lbEvent_help ;Set up the event type
510 BL lb__dispatch ;Dispatch the event
511 LDMFD R13!,{R0-R5,PC}^ ;Return to caller
512
513 ; --- Handle data saves and loads ---
514
515 10lb__message CMP R0,#1 ;Is it a save message?
516 MOVEQ R5,#lbDrop_save ;Set up the subreason code
517 MOVNE R5,#lbDrop_load
518
519 MOV R6,R1 ;Remember the block pointer
520 SUB R13,R13,#52 ;Get a nice block
521 MOV R1,R13 ;Point to it
522 SWI Wimp_GetPointerInfo ;Get pointer information
523 BL lb__getItem ;Get the item under pointer
524 ADD R13,R13,#52 ;Get the stack back
525
526 LDR R2,[R6,#40] ;Load the file type
527 ADD R3,R6,#44 ;Point to the filename
528 LDR R4,[R6,#36] ;Load the estimated size
529 MOV R0,#lbEvent_drop ;The event type
530 BL lb__dispatch ;Dispatch the event
531 LDMFD R13!,{R0-R5,PC}^ ;Return to caller
532
533 LTORG
534
535 ; --- lb__getItem ---
536 ;
537 ; On entry: R1 == pointer to a mouse info block
538 ; R10 == pointer to the listbox
539 ;
540 ; On exit: R1 == the item
541 ;
542 ; Use: Returns the item the pointer is over
543
544 lb__getItem ROUT
545
546 STMFD R13!,{R0,R2-R4,R9,R14} ;Stack some registers
547 MOV R9,R1 ;Keep the mouse info block
548 SUB R13,R13,#36 ;Get me a nice block
549 LDR R0,[R9,#12] ;The window handle
550 STR R0,[R13,#0] ;Store it in the block
551 MOV R1,R13 ;Point to the block
552 SWI Wimp_GetWindowState ;Get the window state
553
554 LDR R2,[R13,#16] ;y1 coord
555 LDR R14,[R13,#24] ;Scroll y position
556 SUB R2,R2,R14 ;Screen coord of origin
557 LDR R14,[R9,#4] ;Mouse y position
558 SUB R2,R14,R2 ;Window relative position
559 ADD R13,R13,#36 ;Get stack back
560 BL screen_getInfo ;Get screen information
561 LDR R14,[R0,#screen_dy] ;Get y pixel size
562 ADD R0,R2,R14 ;Prepare for division
563 LDR R1,[R10,#lb__iHeight] ;By the item height
564 RSB R1,R1,#0 ;Negate it
565 BL divide ;Perform the division
566 MOV R1,R0 ;Put index in R1
567 LDR R0,[R10,#lb__list] ;And list head in R0
568 LDR R4,[R10,#lb__descriptor] ;Get the descriptor block
569 MOV R14,PC ;Set up the return address
570 ADD PC,R4,#lb_indexToItem ;Get the item itself
571 LDMFD R13!,{R0,R2-R4,R9,PC}^ ;Return to caller
572
573 LTORG
574
575 ; --- lb__redraw ---
576 ;
577 ; On entry: R1 == pointer to a window handle
578 ;
579 ; On exit: CS
580 ;
581 ; Use: Redraws a list box, by sending redraw events to the client.
582
583 lb__redraw ROUT
584
585 STMFD R13!,{R0-R9,R14} ;Save masses of registers
586
587 ; --- Start a redraw job ---
588
589 SWI Wimp_RedrawWindow ;Start the redraw
590 CMP R0,#0 ;Is there anything to do?
591 BEQ %90lb__redraw ;No -- don't do it then
592
593 ; --- Do some setting up ---
594
595 ADD R14,R1,#16 ;Point to the top edge
596 LDMIA R14,{R0,R9,R14} ;Load that and the scroll pos
597 SUB R7,R0,R14 ;Work out the y origin pos
598
599 ; --- Get the left and right sides set up ---
600
601 LDR R4,[R10,#lb__maxWidth] ;Get the width of the items
602 LDR R14,[R10,#lb__width] ;Get the window width
603 CMP R14,R4 ;Is the window width bigger?
604 MOVGT R4,R14 ;Yes -- use that instead
605
606 LDR R9,[R10,#lb__descriptor] ;Load his list descriptor
607 LDR R8,[R10,#lb__list] ;Find the list block
608
609 ; --- Work out which bits need drawing ---
610
611 10lb__redraw LDR R6,[R1,#40] ;Load the top y coordinate
612 SUB R6,R6,R7 ;Convert to window coords
613 LDR R14,[R10,#lb__iHeight] ;Get the item height
614 ADD R6,R6,R14 ;Get height thingy value
615
616 MOV R5,#0 ;Top of the first item
617 MOV R1,#0 ;Start at item -1 (sort of)
618
619 ; --- Get items until one is visible ---
620
621 15lb__redraw MOV R0,R8 ;Point to the list block
622 MOV R2,#0 ;Don't care about the flags
623 MOV R3,#0 ;I *really* don't care at all
624 MOV R14,PC ;Set up the return address
625 ADD PC,R9,#lb_enumerate ;Get a new item in R1
626 BCC %70lb__redraw ;Run out -- 76 for 3
627
628 CMP R5,R6 ;Is this item visible?
629 LDRGT R14,[R10,#lb__iHeight] ;No -- get the item height
630 SUBGT R5,R5,R14 ;Move to the next one down
631 BGT %15lb__redraw ;And find one that is then
632
633 ; --- Now draw items until they stop being visible ---
634
635 LDR R6,[R13,#4] ;Get the redraw block pointer
636 LDR R6,[R6,#32] ;Load the bottom y coordinate
637 SUB R6,R6,R7 ;And convert to window coords
638
639 ; --- The main plotting loop ---
640
641 20lb__redraw CMP R5,R6 ;Is this one visible?
642 BLE %80lb__redraw ;No -- then stop plotting
643
644 MOV R0,#lbEvent_redraw ;Send a redraw event on
645 LDR R14,[R10,#lb__iHeight] ;Get the item height
646 SUB R3,R5,R14 ;Get the item bottom bit
647 MOV R2,#0 ;Left hand side is at 0
648 BL lb__dispatch ;Send the event on then
649
650 MOV R5,R3 ;Move to the next item down
651 MOV R0,R8 ;Point to the list block
652 MOV R2,#0 ;Don't care about the flags
653 MOV R3,#0 ;I *really* don't care at all
654 MOV R14,PC ;Set up the return address
655 ADD PC,R9,#lb_enumerate ;Get a new item in R1
656 BCS %20lb__redraw ;More to do -- go round again
657
658 ; --- Fill in the rest in grey ---
659
660 CMP R5,R6 ;Do we really have to draw it
661 BLE %80lb__redraw ;No -- then stop plotting
662
663 70lb__redraw MOV R0,#1 ;The background colour
664 SWI Wimp_SetColour ;Set the colour up
665 ADD R2,R5,R7 ;Get the top of the area
666 BL screen_getInfo ;Read some screen information
667 MOV R14,#1 ;This will be shifty
668 LDR R0,[R0,#screen_yEig] ;Load the y eigen factor
669 SUB R2,R2,R14,LSL R0 ;S*dding thing's exclusive
670 LDR R3,[R13,#4] ;Load the redraw block addr
671 LDR R1,[R3,#28] ;Load the left hand side
672 MOV R0,#4 ;Move cursor absolute
673 SWI OS_Plot ;Do the plotting bit
674 MOV R0,#101 ;Rectangle fill absolute
675 LDR R1,[R3,#36] ;Get the right hand side
676 LDR R2,[R3,#32] ;And the bottom edge
677 SWI OS_Plot ;Fill in the remaining bit
678
679 ; --- Go round and get another rectangle ---
680
681 80lb__redraw LDR R1,[R13,#4] ;Get the redraw block pointer
682 SWI Wimp_GetRectangle ;Get the next rectangle
683 CMP R0,#0 ;Is there more to draw?
684 BNE %10lb__redraw ;Yes -- go round again
685
686 ; --- We finished at last ---
687
688 90lb__redraw LDMFD R13!,{R0-R9,R14} ;Unstack the registers again
689 ORRS PC,R14,#C_flag ;More redraws cause flicker
690
691 LTORG
692
693 ; --- lb__close ---
694 ;
695 ; On entry: --
696 ;
697 ; On exit: --
698 ;
699 ; Use: Informs the user when the listbox has been closed.
700
701 lb__close ROUT
702
703 STMFD R13!,{R0,R14} ;Stack some register
704 MOV R0,#lbEvent_close ;Send this event code
705 BL lb__dispatch ;And dispatch the event
706 LDMFD R13!,{R0,PC} ;Return to caller
707
708 LTORG
709
710 ; --- lb__scroll ---
711 ;
712 ; On entry: R0 == 10
713 ; R1 == event block
714 ;
715 ; On exit: --
716
717 lb__scroll ROUT
718
719 STMFD R13!,{R0-R4,R14} ;Stack some registers
720 MOV R4,R1 ;Keep the block pointer
721
722 ; --- First, try to scroll vertically ---
723
724 LDR R0,[R4,#24] ;Load the y scroll offset
725 ADD R14,R4,#8 ;Find the bottom edge
726 LDMIA R14,{R2,R3,R14} ;Load the y positions
727 SUB R3,R14,R2 ;R3 is the window height now
728 LDR R2,[R10,#lb__iHeight] ;Get the item height
729
730 LDR R14,[R1,#36] ;Get vertical scroll value
731 ADD R14,R14,#1 ;Convert into range -1..3
732 ADD PC,PC,R14,LSL #2 ;And jump to right routine
733
734 B %10lb__scroll ;Y scroll page down
735 B %20lb__scroll ;Y scroll line down
736 B %50lb__scroll ;No y scrolling
737 B %40lb__scroll ;Y scroll line up
738 B %30lb__scroll ;Y scroll page up
739
740 ; --- Do a y scroll page down ---
741
742 10lb__scroll SUB R0,R0,R3 ;Find the window bottom
743 MOV R1,R2 ;Now prepare to divide by it
744 SUB R0,R0,R2 ;Make it round towards 0
745 BL divide ;Get the quotient value
746 MUL R0,R2,R0 ;And multiply it up again
747 ADD R0,R0,R2,LSL #1 ;Find the appropriate top
748 STR R0,[R4,#24] ;Store the scroll offset back
749 B %50lb__scroll ;And now do the x bit
750
751 ; --- Do a y scroll line down ---
752
753 20lb__scroll SUB R0,R0,R3 ;Find the window bottom
754 MOV R1,R2 ;Now prepare to divide by it
755 SUB R0,R0,R2 ;Make it round towards 0
756 BL divide ;Get the quotient value
757 MUL R0,R2,R0 ;And multiply it up again
758 ADD R0,R0,R3 ;Find the appropriate top
759 STR R0,[R4,#24] ;Store the scroll offset back
760 B %50lb__scroll ;And now do the x bit
761
762 ; --- Do a y scroll page up ---
763
764 30lb__scroll MOV R1,R2 ;Now prepare to divide by it
765 ADD R0,R0,#1 ;Make it round towards 0
766 BL divide ;Get the quotient value
767 MUL R0,R2,R0 ;And multiply it up again
768 ADD R0,R0,R3 ;Scroll the whole window up
769 SUB R0,R0,R2,LSL #1 ;And scroll back two items
770 STR R0,[R4,#24] ;Store the scroll offset back
771 B %50lb__scroll ;And now do the x bit
772
773 ; --- Do a y scroll line up ---
774
775 40lb__scroll MOV R1,R2 ;Now prepare to divide by it
776 ADD R0,R0,#1 ;Make it round towards 0
777 BL divide ;Get the quotient value
778 MUL R0,R2,R0 ;And multiply it up again
779 STR R0,[R4,#24] ;Store the scroll offset back
780 B %50lb__scroll ;And now do the x bit
781
782 ; --- Now do the x scrolling ---
783
784 50lb__scroll LDR R0,[R4,#20] ;Load the x scroll offset
785 ADD R14,R4,#4 ;Find the left hand side
786 LDMIA R14,{R2,R3,R14} ;Load the x positions
787 SUB R3,R14,R2 ;Get the current window width
788
789 LDR R14,[R4,#32] ;Get horizontal scroll value
790 CMP R14,#-2 ;Scroll left by a page?
791 SUBEQ R0,R0,R3 ;Yes -- do it then
792 CMP R14,#-1 ;Scroll left by a column?
793 SUBEQ R0,R0,#32 ;Yes -- do it then
794 CMP R14,#1 ;Scroll right by a column?
795 ADDEQ R0,R0,#32 ;Yes -- do it then
796 CMP R14,#2 ;Scroll right by a page?
797 ADDEQ R0,R0,R3 ;Yes -- do it then
798 STR R0,[R4,#20] ;Save the x scroll offset
799
800 99lb__scroll MOV R1,R4 ;Point to the block again
801 SWI Wimp_OpenWindow ;Actually do the scrolling
802 LDMFD R13!,{R0-R4,R14} ;Return to caller
803 ORRS PC,R14,#C_flag
804
805 LTORG
806
807 ; --- lb_plotString ---
808 ;
809 ; On entry: R0 == pointer to a string
810 ; R1 == pointer to the list item
811 ; R2-R5 == window coordinates to plot it
812 ; R10 == pointer to the listbox
813 ;
814 ; On exit: --
815 ;
816 ; Use: Plots a list item consisting of a single string. It assumes
817 ; the default selection model.
818
819 EXPORT lb_plotString
820 lb_plotString ROUT
821
822 STMFD R13!,{R0-R4,R14} ;Save a lot of registers
823 SUB R13,R13,#32 ;Make an icon block
824 STMIA R13,{R2-R5} ;Save the coordinates in it
825 MOV R2,#-1 ;No validation string
826 MOV R3,#1 ;Put in a silly buffer size
827 ADD R14,R13,#20 ;Point to icon data section
828 STMIA R14,{R0,R2,R3} ;Save the icon data away
829 LDR R4,[R10,#lb__descriptor] ;Get the descriptor block
830 LDR R0,[R10,#lb__list] ;Point to the list head
831 MOV R2,#0 ;Don't alter the flags
832 MOV R3,#0 ;Don't alter them at all
833 MOV R14,PC ;Set up return address
834 ADD PC,R4,#lb_setFlags ;Read the item's flags
835 LDR R0,=&07000131 ;Set up default flags
836 TST R2,#3 ;Is it selected?
837 ORRNE R0,R0,#&00200000 ;Yes -- set the selected bit
838 STR R0,[R13,#16] ;Store the flags in the blk
839 MOV R1,R13 ;Point to the icon block
840 SWI Wimp_PlotIcon ;Plot the icon then
841 ADD R13,R13,#32 ;Recover the icon block
842 LDMFD R13!,{R0-R4,PC}^ ;Return to caller
843
844 LTORG
845
846 ; --- lb_update ---
847 ;
848 ; On entry: R0 == listbox handle
849 ;
850 ; On exit: May return an error
851 ;
852 ; Use: Updates the entire listbox prettily
853
854 EXPORT lb_update
855 lb_update ROUT
856
857 STMFD R13!,{R0-R4,R10,R14} ;Stack sonme registers
858
859 MOV R10,R0 ;Put list box handle in R10
860 BL lb__getMaxWidth ;Get the maximum width
861 BL lb__rescanSize ;Ensure windows right size
862 BVS %90lb_update ;Barf on error
863 LDR R0,[R10,#lb__wHandle] ;Get the window handle
864 MOV R1,#0 ;x0
865 LDR R2,[R10,#lb__height] ;Overall height
866 RSB R2,R2,#0 ;Negate it
867 LDR R3,[R10,#lb__width] ;Overall width -- x1
868 LDR R14,[R10,#lb__maxWidth] ;And the widest item width
869 CMP R14,R3 ;Which one is bigger?
870 MOVGT R3,R14 ;Make R3 biggest
871 MOV R4,#0 ;y1
872 SWI Wimp_ForceRedraw ;Force a redraw
873
874 LDMFD R13!,{R0-R4,R10,PC}^ ;Return to caller
875
876 90lb_update ADD R13,R13,#4 ;Point past R0
877 LDMFD R13!,{R1-R4,R10,R14} ;Get back some registers
878 ORRS PC,R14,#V_flag ;Return with error
879
880 LTORG
881
882 ; --- lb_updateItem ---
883 ;
884 ; On entry: R0 == list box handle
885 ; R1 == list item handle
886 ;
887 ; On exit: --
888 ;
889 ; Use: Redraws a list item to reflect a change in its state.
890
891 EXPORT lb_updateItem
892 lb_updateItem ROUT
893
894 STMFD R13!,{R0-R5,R10,R14} ;Save a load of registers
895
896 ; --- Find the item's index ---
897
898 MOV R10,R0 ;Keep the list box handle
899 LDR R0,[R10,#lb__list] ;Find the list block
900 LDR R2,[R10,#lb__descriptor] ;Find the list descriptor
901 MOV R14,PC ;Set up the return address
902 ADD PC,R2,#lb_itemToIndex ;Get the item's index
903
904 ; --- Now set up the update block ---
905
906 SUB R13,R13,#44 ;Make space for update blk
907 LDR R0,[R10,#lb__wHandle] ;Get the window handle
908 LDR R14,[R10,#lb__iHeight] ;Get the item height
909 RSB R14,R14,#0 ;Negate it
910 MUL R5,R14,R1 ;Get the top of the item
911 ADD R3,R5,R14 ;And get the bottom too
912 MOV R2,#0 ;Redraw from left hand side
913 LDR R4,[R10,#lb__width] ;Load the window width
914 LDR R14,[R10,#lb__maxWidth] ;And the widest item width
915 CMP R14,R4 ;Which one is bigger?
916 MOVGT R4,R14 ;Use the biggest one
917 STMIA R13,{R0,R2-R5} ;Save them in the block
918
919 ; --- Update the item ---
920
921 MOV R1,R13 ;Point to the window block
922 SWI Wimp_UpdateWindow ;Start doing the update
923 CMP R0,#0 ;Is there anything to do?
924 BEQ %90lb_updateItem ;No -- skip it all then
925
926 10lb_updateItem MOV R0,#lbEvent_redraw ;Send out a redraw event
927 LDR R1,[R13,#48] ;Get the item handle
928 BL lb__dispatch ;Give the user an event
929 MOV R1,R13 ;Point to the update block
930 SWI Wimp_GetRectangle ;Get another rectangle
931 CMP R0,#0 ;Was that the last one?
932 BNE %10lb_updateItem ;No -- do another one then
933
934 ; --- Tidy up and go home again ---
935
936 90lb_updateItem ADD R13,R13,#44 ;Restore the stack pointer
937 LDMFD R13!,{R0-R5,R10,PC}^ ;And return to the caller
938
939 LTORG
940
941 ; --- lb_select ---
942 ;
943 ; On entry: R0 == listbox handle
944 ; R1 == item handle
945 ; R2 == 0 to unselect, 1 to select, or 2 to toggle
946 ;
947 ; On exit: --
948 ;
949 ; Use: Selects or deselects a listbox item, nicely and without
950 ; flickering it.
951
952 EXPORT lb_select
953 lb_select ROUT
954
955 CMP R1,#0 ;Is there actually an item?
956 MOVEQS PC,R14 ;No -- then do nothing here
957
958 STMFD R13!,{R0-R5,R10,R14} ;Save some registers away
959 MOV R10,R0 ;Get the listbox handle
960
961 ; --- Read the current flags ---
962
963 LDR R4,[R10,#lb__descriptor] ;Find the list definition
964 MOV R5,R2 ;And look after argument
965 MOV R3,#0 ;Want to read the flags
966 MOV R2,#0 ;Oh, yes I do
967 LDR R0,[R10,#lb__list] ;Load the list block
968 MOV R14,PC ;Set up the return address
969 ADD PC,R4,#lb_setFlags ;And read the current flags
970
971 ; --- Work out new flags ---
972
973 AND R2,R2,#1 ;Only leave selected flag
974 CMP R5,#1 ;What is the operation?
975 MOVLT R3,#0 ;Clear -- clear the flag
976 MOVEQ R3,#1 ;Set -- set the flag
977 EORGT R3,R2,#1 ;Toggle -- toggle the flag
978 CMP R3,R2 ;Have we made a difference?
979 LDMEQFD R13!,{R0-R5,R10,PC}^ ;No -- return now then
980
981 ; --- Set the new flags ---
982
983 MOV R2,#1 ;Clear the selected bit
984 MOV R14,PC ;Set up return address
985 ADD PC,R4,#lb_setFlags ;Set the new flags nicely
986 MOV R0,R10 ;Get handle in R0
987 BL lb_updateItem ;And redraw the list item
988 LDMFD R13!,{R0-R5,R10,PC}^ ;And return to caller
989
990 LTORG
991
992 ; --- lb_isSelected ---
993 ;
994 ; On entry: R0 == listbox handle
995 ; R1 == item handle
996 ;
997 ; On exit: CS if item is selected, else CC
998 ;
999 ; Use: Informs you whether an item is selected.
1000
1001 EXPORT lb_isSelected
1002 lb_isSelected ROUT
1003
1004 CMP R1,#0 ;Is there an icon?
1005 BICEQS PC,R14,#C_flag ;No -- not selected then
1006 STMFD R13!,{R0-R4,R14} ;Save some registers
1007 MOV R2,#0 ;Don't clear any flags
1008 MOV R3,#0 ;Don't toggle any either
1009 LDR R4,[R0,#lb__descriptor] ;Find the list block
1010 LDR R0,[R0,#lb__list] ;Find the list base
1011 MOV R14,PC ;Set up return address
1012 ADD PC,R4,#lb_setFlags ;Read the current flags
1013 TST R2,#1 ;Is it selected then?
1014 LDMFD R13!,{R0-R4,R14} ;Restore caller's registers
1015 ORRNES PC,R14,#C_flag ;If selected, return C set
1016 BICEQS PC,R14,#C_flag ;Otherwise clear C on exit
1017
1018 LTORG
1019
1020 ; --- lb__click ---
1021 ;
1022 ; On entry: R1 == pointer to event block
1023 ;
1024 ; On exit: CS
1025 ;
1026 ; Use: Dispatches click events on the list box
1027
1028 lb__click ROUT
1029
1030 ORR R14,R14,#C_flag ;Set the carry flag
1031 STMFD R13!,{R0-R4,R9,R14} ;Stack some registers
1032 MOV R9,R1 ;Keep a pointer to the block
1033
1034 BL lb__getItem ;Get item pointer is over
1035
1036 LDR R3,[R9,#8] ;Get the mouse button status
1037 TST R3,#&5 ;Double select or ajdust
1038 TSTEQ R3,#&500 ;No -- just select or adjust?
1039 BNE %10lb__click ;Yes -- handle it then
1040 TST R3,#&50 ;Drag with select or adjust?
1041 BNE %20lb__click ;Yes -- deal with that
1042 TST R3,#&2 ;Is it menu click?
1043 LDMEQFD R13!,{R0-R3,R9,PC}^ ;no -- return then
1044
1045 ; --- Deal with menu clicks ---
1046
1047 MOV R0,#lbEvent_menu ;The event type
1048 BL lb__dispatch ;Dispatch the event
1049 B %99lb__click ;And return to caller
1050
1051 ; --- Click or double click on an item ---
1052
1053 10 MOV R0,#lbEvent_click ;The event type
1054 BL lb__dispatch ;Dispatch the event
1055 B %99lb__click ;And return to caller
1056
1057 ; --- There was a drag event ---
1058
1059 20 MOV R0,#lbEvent_drag ;The event type
1060 BL lb__dispatch ;Dispatch the event
1061 B %99lb__click ;And return to caller
1062
1063 99 LDMFD R13!,{R0-R4,R9,PC}^ ;Return to caller
1064
1065 LTORG
1066
1067 ; --- lb_clearSelection ---
1068 ;
1069 ; On entry: R0 == listbox handle
1070 ; R1 == item handle of item to ignore (or 0 for none)
1071 ;
1072 ; On exit: --
1073 ;
1074 ; Use: Deselects all items in the listbox.
1075
1076 EXPORT lb_clearSelection
1077 lb_clearSelection ROUT
1078
1079 STMFD R13!,{R0-R6,R10,R14} ;Stack some registers
1080 MOV R10,R0 ;Get the listbox handle
1081 LDR R6,[R10,#lb__list] ;And load the list pointer
1082 MOV R5,R1 ;Remember this item
1083 LDR R4,[R10,#lb__descriptor] ;Point to the descriptor blk
1084
1085 MOV R1,#0 ;Start with the first item
1086 00 MOV R0,R6 ;Get the list handle
1087 MOV R2,#1 ;Only read selected items
1088 MOV R3,#1 ;Don't want the others
1089 MOV R14,PC ;Set up return address
1090 ADD PC,R4,#lb_enumerate ;Read the item and flags
1091 BCC %90 ;No more items -- skip
1092
1093 CMP R1,R5 ;Is this the special item?
1094 BEQ %b00 ;Yes -- ignore it then
1095 MOV R0,R10 ;No -- get the list handle
1096 MOV R2,#0 ;Deselect it please
1097 BL lb_select ;And unselect the item
1098 B %b00 ;And loop back again
1099
1100 90 LDMFD R13!,{R0-R6,R10,PC}^ ;Return to caller
1101
1102 LTORG
1103
1104 ; --- lb_clickS ---
1105 ;
1106 ; On entry: R0 == listbox handle
1107 ; R1 == pointer to list item
1108 ; R3 == mouse button status
1109 ;
1110 ; On exit: --
1111 ;
1112 ; Use: Provides a default action for clicking on an item in a
1113 ; list box.
1114 ;
1115 ; Only one selection is possible at any one time.
1116
1117 EXPORT lb_clickS
1118 lb_clickS ROUT
1119
1120 STMFD R13!,{R0,R2,R14} ;Stack some registers
1121 BL lb_clearSelection ;Clear all the other items
1122 TST R3,#&100 ;Is it an adjust click?
1123 TSTEQ R3,#&001 ;Better check the double too
1124 MOVNE R2,#2 ;Yes -- then toggle the item
1125 MOVEQ R2,#1 ;Otherwise just select
1126 BL lb_select ;Go and select the item
1127 LDMFD R13!,{R0,R2,PC}^ ;Return to caller
1128
1129 LTORG
1130
1131 ; --- lb_clickM ---
1132 ;
1133 ; On entry: R0 == listbox handle
1134 ; R1 == pointer to list item
1135 ; R3 == mouse button status
1136 ;
1137 ; On exit: --
1138 ;
1139 ; Use: Provides a default action for clicking on an item in a
1140 ; list box.
1141 ;
1142 ; The multiple selection model is used.
1143
1144 EXPORT lb_clickM
1145 lb_clickM ROUT
1146
1147 STMFD R13!,{R0,R2,R14} ;Stack some registers
1148 TST R3,#&100 ;Is it an adjust click?
1149 TSTEQ R3,#&001 ;Better check the double too
1150 BEQ %50lb_clickM ;No -- then deal elsewhere
1151 MOV R2,#2 ;Just toggle the item
1152 BL lb_select ;Do the selecting bit
1153 B %90lb_clickM ;And skip onwards
1154 50lb_clickM BL lb_isSelected ;Is the item selected?
1155 BLCC lb_clearSelection ;No -- then clear the others
1156 MOVCC R2,#1 ;Select this item
1157 BLCC lb_select ;Go and do that
1158 90lb_clickM LDMFD R13!,{R0,R2,PC}^ ;Return to caller
1159
1160 LTORG
1161
1162 ; --- lb__idleHandler ---
1163 ;
1164 ; On entry: R10 == listbox handle
1165 ; R12 == workspace pointer ;
1166 ; On exit: --
1167 ;
1168 ; Use: Called on NULL events during a drag
1169
1170 lb__idleHandler ROUT
1171
1172 STMFD R13!,{R0-R9,R14} ;Stack some registers
1173
1174 SUB R13,R13,#56 ;Get a block
1175 MOV R1,R13 ;Point to it
1176 SWI Wimp_GetPointerInfo ;Get pointer position
1177 LDR R0,[R10,#lb__wHandle] ;Get the window handle
1178 STR R0,[R13,#20] ;Store in the block
1179 ADD R1,R13,#20 ;Point to the block
1180 SWI Wimp_GetWindowState ;Get the window state
1181 LDR R9,[R13,#36] ;Get the y1 coordinate
1182 LDR R14,[R13,#44] ;The scroll coordinate
1183 SUB R9,R9,R14 ;Window origin
1184 LDR R14,[R13,#4] ;Mouse y position
1185 SUB R9,R14,R9 ;Make it window relative
1186
1187 BL screen_getInfo ;Get screen information
1188 LDR R14,[R0,#screen_dy] ;Get y pixel size
1189 ADD R0,R9,R14 ;Prepare for division
1190 LDR R1,[R10,#lb__iHeight] ;By the item height
1191 RSB R1,R1,#0 ;Negate it
1192 BL divide ;Perform the division
1193 CMP R0,#0 ;Is index negative?
1194 MOVLT R0,#0 ;Yes -- make it 0
1195
1196 LDR R6,ws__dragItem ;Get start drag index
1197 LDR R3,ws__dragLast ;And last drag position
1198 MOV R8,R0 ;Copy index into R1
1199 MOV R7,R0 ;And R7
1200 MOV R5,R0 ;And R5
1201
1202 ; --- Find minimum and maximum values ---
1203
1204 CMP R7,R6 ;R0>R2?
1205 MOVGT R7,R6 ;Yes == R0:=R2
1206 CMP R7,R3 ;R0>R3?
1207 MOVGT R7,R3 ;Yes == R0:=R3
1208
1209 CMP R8,R6 ;R0<R2?
1210 MOVLT R8,R6 ;Yes == R0:=R2
1211 CMP R8,R3 ;R0<R3?
1212 MOVLT R8,R3 ;Yes == R0:=R3
1213
1214 ; --- Summary ---
1215 ;
1216 ; R5 == the current index
1217 ; R6 == the initial index
1218 ; R7 == minimum of current,last and initial drag indicies
1219 ; R8 == maximum of current,last and initial drag indicies
1220 ; R9 == window relative position of the mouse position
1221
1222 STMFD R13!,{R12} ;We need this -- blurgg!!
1223 LDR R12,[R10,#lb__descriptor] ;Point to descriptor block
1224 MOV R4,#-1 ;Current item index (i)
1225 MOV R3,#-1 ;The selection type
1226 LDR R0,[R10,#lb__list] ;Get the list head
1227 MOV R1,#0 ;Start from the first item
1228
1229 00 STMFD R13!,{R3} ;Preserve R3 over call
1230 MOV R2,#0 ;Interested in all items
1231 MOV R3,#0 ;Interested in all items
1232 MOV R14,PC ;Set up return address
1233 ADD PC,R12,#lb_enumerate ;Call enumeration function
1234 LDMFD R13!,{R3} ;Get R3 back again
1235 BCC %50lb__idleHandler ;No more -- exit the loop
1236 ADD R4,R4,#1 ;Increment index count
1237
1238 CMP R4,R7 ;i == start index?
1239 MOVEQ R3,#0 ;Yes -- sel=0
1240 CMP R6,R5 ;Initial index<index
1241 BGT %20lb__idleHandler ;No -- jump ahead then
1242
1243 CMP R4,R6 ;i=initial index?
1244 MOVEQ R3,#1 ;Yes -- sel=1
1245 CMP R4,R5 ;i>current index?
1246 MOVGT R3,#0 ;Yes -- sel=0
1247 B %30lb__idleHandler ;Jump ahead a bit
1248
1249 20 CMP R4,R5 ;i=current index?
1250 MOVEQ R3,#1 ;Yes -- sel=1
1251 CMP R4,R6 ;i>initial index?
1252 MOVGT R3,#0 ;Yes -- sel=0
1253 B %30lb__idleHandler ;Jump ahead a bit
1254
1255 30 CMP R4,R8 ;Are we at the end?
1256 BGT %50lb__idleHandler ;Yes -- jump out of loop
1257
1258 ; --- Redraw the item if we need to ---
1259
1260 CMP R3,#-1 ;Do we need to do anything?
1261 BEQ %00lb__idleHandler ;No -- keep going round
1262 STMFD R13!,{R0-R4} ;Stack some registers
1263 LDR R0,[R10,#lb__list] ;Get the list head
1264 MOV R4,R3 ;Look after thing in R3
1265 MOV R2,#0 ;Read the flags
1266 MOV R3,#0 ;No writing here
1267 MOV R14,PC ;Set up return address
1268 ADD PC,R12,#lb_setFlags ;Read the flags
1269 ORR R3,R2,R2,LSR#1 ;Is bit 0 or 1 set?
1270 AND R3,R3,#1 ;Just interested in this bit
1271 CMP R3,R4 ;Is there a change to be made
1272 BEQ %40lb__idleHandler ;No -- keep on looping then
1273 ANDS R2,R2,#1 ;Just get selected bit
1274 BEQ %35lb__idleHandler ;If its clear -- jump ahead
1275 CMP R2,R4 ;Is this the same?
1276 BNE %40lb__idleHandler ;No -- return
1277 35 MOV R2,#2 ;Just alter this bit
1278 MOV R3,R4,LSL#1 ;Set or clear appropriately
1279 LDR R0,[R10,#lb__list] ;Get the list head
1280 MOV R14,PC ;Set up return address
1281 ADD PC,R12,#lb_setFlags ;Set the flags
1282 MOV R0,R10 ;Put listbox handle in R0
1283 BL lb_updateItem ;Update the item
1284
1285 40 LDMFD R13!,{R0-R4} ;Restore registers
1286 B %00lb__idleHandler ;Keep going round
1287
1288 50 LDMFD R13!,{R12} ;Get R12 back again
1289 STR R5,ws__dragLast ;Store last item visited
1290
1291 ; --- Scroll the window nicely ---
1292
1293 LDR R0,[R13,#44] ;Get the y scroll position
1294 CMP R9,R0 ;Is mouse y>y scroll?
1295 MOVGT R0,R9 ;Yes -- y scroll=mouse y
1296 BGT %55lb__idleHandler ;...and jump ahead
1297 LDR R2,[R13,#36] ;Get y1 coordinate
1298 LDR R3,[R13,#28] ;Get y0 coordinate
1299 SUB R3,R2,R3 ;Get window height
1300 ADD R9,R9,R3 ;Add on mouse position
1301 CMP R9,R0 ;Is it less than y scroll pos
1302 MOVLT R0,R9 ;Yes -- use y scroll pos
1303 55 STR R0,[R13,#44] ;Store new scroll position
1304 ADD R1,R13,#20 ;Point to the block
1305 SWI Wimp_OpenWindow ;Open the window
1306
1307 99 ADD R13,R13,#56 ;Reclaim the stack
1308 99 LDMFD R13!,{R0-R9,PC}^ ;Return to caller
1309
1310 LTORG
1311
1312 ; --- lb__unknownHandler ---
1313 ;
1314 ; On entry: R0 == event type
1315 ; R1 == event block
1316 ; R10 == listbox handle
1317 ; R12 == workspace pointer
1318 ;
1319 ; On exit: --
1320 ;
1321 ; Use: Called when the drag is ended
1322
1323
1324 lb__unknownHandler ROUT
1325
1326 CMP R0,#7 ;Are we interested?
1327 MOVNES PC,R14 ;No -- return PDQ
1328
1329 STMFD R13!,{R0-R4,R14} ;Stack some registers
1330
1331 ; --- First get rid of the idle claimer ---
1332
1333 MOV R0,#0 ;Call very frequently
1334 ADR R1,lb__idleHandler ;Call this routine
1335 MOV R2,R10 ;Call with this R10 handle
1336 MOV R3,R12 ;And this R12 value
1337 BL idle_removeHandler ;Add in the handler
1338
1339 ; --- Now this unknown handler ---
1340
1341 ADR R0,lb__unknownHandler ;Call this routine
1342 MOV R1,#0 ;R4 value
1343 MOV R2,R10 ;Call with this R10 handle
1344 MOV R3,R12 ;And this R12 value
1345 BL win_removeUnknownHandler ;Add in the handler
1346
1347 ; --- Make temporary selections permanant ---
1348
1349 LDR R4,[R10,#lb__descriptor] ;Point to descriptor block
1350 LDR R0,[R10,#lb__list] ;Get the list head
1351 MOV R1,#0 ;Start from the top
1352 00 MOV R2,#2 ;Just interested in this bit
1353 MOV R3,#2 ;And it must be set
1354 MOV R14,PC ;Set up the return address
1355 ADD PC,R4,#lb_enumerate ;Enumerate the list
1356 BCC %99lb__unknownHandler ;No more -- return
1357
1358 LDR R0,[R10,#lb__list] ;Get the list head
1359 MOV R2,#3 ;Clear these bits
1360 MOV R3,#1 ;And set this one
1361 MOV R14,PC ;Set up the return address
1362 ADD PC,R4,#lb_setFlags ;And set the flags
1363 B %00lb__unknownHandler ;Keep going round for more
1364
1365 99 LDMFD R13!,{R0-R4,PC}^ ;Return to caller
1366
1367 LTORG
1368
1369 ; --- lb_drag ---
1370 ;
1371 ; On entry: R0 == listbox handle
1372 ; R1 == pointer to list item
1373 ; R3 == mouse button status
1374 ;
1375 ; On exit: --
1376 ;
1377 ; Use: Starts a drag operation to allow for easy multiple
1378 ; selection.
1379
1380 EXPORT lb_drag
1381 lb_drag ROUT
1382
1383 STMFD R13!,{R0-R3,R10,R12,R14} ;Stack some registers
1384 WSPACE lb__wSpace ;Locate my workspace
1385 MOV R10,R0 ;Move listbox handle into R10
1386
1387 LDR R0,[R10,#lb__list] ;Point to the list head
1388 LDR R2,[R10,#lb__descriptor] ;Point to descriptor block
1389 CMP R1,#0 ;Is there an item
1390 MOVEQ R3,#lb_items ;No -- use the item count
1391 MOVNE R3,#lb_itemToIndex ;Yes -- find its index
1392 MOV R14,PC ;Set up return address
1393 ADD PC,R2,R3 ;Convert item to an index
1394 STR R1,ws__dragItem ;The start drag item
1395 STR R1,ws__dragLast ;Last item visited
1396
1397 ; --- First we must start the drag box ---
1398
1399 SUB R13,R13,#40 ;Get me a block
1400 MOV R1,R13 ;Point to the block
1401 SWI Wimp_GetPointerInfo ;Get mouse position
1402 LDR R0,[R1,#0] ;Get mouse x position
1403 LDR R1,=&9001 ;Parent y0
1404 MOV R2,R0 ;Parent x1
1405 LDR R3,=&6FFE ;Parent Parent y1
1406 ADD R14,R13,#24 ;Point to right place
1407 STMIA R14,{R0-R3} ;Store parent coords
1408 MOV R0,#7 ;The drag type
1409 STR R0,[R13,#4] ;Store nicely in block
1410 MOV R1,R13 ;Point to the block
1411 SWI Wimp_DragBox ;Start the drag
1412
1413 ; --- Set up the idle event handler ---
1414
1415 MOV R0,#0 ;Call very frequently
1416 ADR R1,lb__idleHandler ;Call this routine
1417 MOV R2,R10 ;Call with this R10 handle
1418 MOV R3,R12 ;And this R12 value
1419 BL idle_handler ;Add in the handler
1420
1421 ; --- Set up the unknown handler ---
1422
1423 ADR R0,lb__unknownHandler ;Call this routine
1424 MOV R1,#0 ;R4 value
1425 MOV R2,R10 ;Call with this R10 handle
1426 MOV R3,R12 ;And this R12 value
1427 BL win_unknownHandler ;Add in the handler
1428
1429 ; --- Now return to the caller ---
1430
1431 ADD R13,R13,#40 ;Reclaim the stack
1432 LDMFD R13!,{R0-R3,R10,R12,PC}^ ;Return to caller
1433
1434 LTORG
1435
1436 ; --- lb_inserted ---
1437 ;
1438 ; On entry: R0 == pointer to the listbox
1439 ; R1 == pointer to the new item
1440 ;
1441 ; On exit: --
1442 ;
1443 ; Use: Informs the listbox that an item has been inserted,
1444 ; and causes a flicker free insert to occur if possible.
1445
1446 EXPORT lb_inserted
1447 lb_inserted ROUT
1448
1449 STMFD R13!,{R0-R8,R10,R14} ;Stack some registers
1450
1451 MOV R10,R0 ;Put listbox handle in R10
1452 MOV R7,R1 ;Look after item
1453 BL lb__getMaxWidth ;Get the maximum width
1454 LDR R2,[R10,#lb__wHandle] ;Get the old window handle
1455 BL lb__rescanSize ;Ensure windows right size
1456 CMP R2,R0 ;Has the window changed?
1457 BNE %99lb_inserted ;Yes -- return
1458
1459 ; --- Now do the block copy ---
1460
1461 LDR R0,[R10,#lb__list] ;Get the list head
1462 LDR R2,[R10,#lb__descriptor] ;Get the descriptor
1463 MOV R14,PC ;Set up the return address
1464 ADD PC,R2,#lb_itemToIndex ;Convert item to index
1465
1466 LDR R8,[R10,#lb__iHeight] ;Get the item height
1467 RSB R8,R8,#0 ;Negate it
1468 MUL R4,R8,R1 ;Get top of item
1469 MOV R14,PC ;Set up return address
1470 ADD PC,R2,#lb_items ;Get the item count
1471 MUL R2,R1,R8 ;The overall height
1472 LDR R0,[R10,#lb__wHandle] ;Get the window handle
1473 MOV R1,#0 ;The minimum x coord
1474 LDR R3,[R10,#lb__width] ;Load the window width
1475 LDR R6,[R10,#lb__maxWidth] ;And the widest item width
1476 CMP R6,R3 ;Which one is bigger?
1477 MOVGT R3,R6 ;Use the biggest one
1478 MOV R5,#0 ;x coord to move to
1479 ADD R6,R2,R8 ;y coord to move to
1480 SWI Wimp_BlockCopy ;Do a block copy
1481
1482 ; --- Finally, update the new item ---
1483
1484 MOV R0,R10 ;Point to the listbox
1485 MOV R1,R7 ;Put item pointer in R1
1486 BL lb_updateItem ;Update the item
1487
1488 99lb_inserted LDMFD R13!,{R0-R8,R10,PC}^ ;Return to caller
1489
1490 LTORG
1491
1492 ; --- lb_removed ---
1493 ;
1494 ; On entry: R0 == pointer to the listbox
1495 ; R1 == index of item removed
1496 ;
1497 ; On exit: --
1498 ;
1499 ; Use: Informs the listbox that an item has been removed, and
1500 ; causes a flicker free remove to occur, if possible.
1501
1502 EXPORT lb_removed
1503 lb_removed ROUT
1504
1505 STMFD R13!,{R0-R8,R10,R14} ;Stack some registers
1506
1507 MOV R10,R0 ;Put listbox handle in R10
1508 MOV R7,R1 ;Look after item
1509 BL lb__getMaxWidth ;Get the maximum width
1510 LDR R2,[R10,#lb__wHandle] ;Get the old window handle
1511 BL lb__rescanSize ;Ensure windows right size
1512 CMP R2,R0 ;Has the window changed?
1513 BNE %99lb_removed ;Yes -- return
1514
1515 ; --- Now do the block copy ---
1516
1517 LDR R2,[R10,#lb__descriptor] ;Get the descriptor block
1518 LDR R8,[R10,#lb__iHeight] ;Get the item height
1519 RSB R8,R8,#0 ;Negate it
1520 MUL R4,R8,R1 ;Get top of item
1521 ADD R4,R4,R8 ;Now get the bottom of it
1522 LDR R0,[R10,#lb__list] ;Get the list head
1523 MOV R14,PC ;Set up return address
1524 ADD PC,R2,#lb_items ;Get the item count
1525 MUL R2,R1,R8 ;The overall height
1526 LDR R3,[R10,#lb__height] ;Get overall window height
1527 SUB R2,R2,R3 ;Subtract that for luck
1528 LDR R0,[R10,#lb__wHandle] ;Get the window handle
1529 MOV R1,#0 ;The minimum x coord
1530 LDR R3,[R10,#lb__width] ;Load the window width
1531 LDR R6,[R10,#lb__maxWidth] ;And the widest item width
1532 CMP R6,R3 ;Which one is bigger?
1533 MOVGT R3,R6 ;Use the biggest one
1534 MOV R5,#0 ;x coord to move to
1535 SUB R6,R2,R8 ;y coord to move to
1536 SWI Wimp_BlockCopy ;Do a block copy
1537
1538 99lb_removed LDMFD R13!,{R0-R8,R10,PC}^ ;Return to caller
1539
1540 LTORG
1541
1542 ; --- lb_window ---
1543 ;
1544 ; On entry: R0 == listbox handle
1545 ;
1546 ; On exit: R0 == window handle
1547 ;
1548 ; Use: Returns the window handle of the listbox
1549
1550 EXPORT lb_window
1551 lb_window ROUT
1552
1553 LDR R0,[R0,#lb__wHandle] ;Load the window handle
1554 MOVS PC,R14 ;Return to caller
1555
1556 LTORG
1557
1558 ; --- lb_init ---
1559 ;
1560 ; On entry: --
1561 ;
1562 ; On exit: --
1563 ;
1564 ; Use: Initialises the listbox unit.
1565
1566 EXPORT lb_init
1567 lb_init ROUT
1568
1569 STMFD R13!,{R12,R14} ;Stack some registers
1570 WSPACE lb__wSpace ;Locate my workspace
1571
1572 ; --- Ensure that we are not already initialised ---
1573
1574 LDR R14,ws__flags ;Get the flags word
1575 TST R14,#wsFlag__inited ;Are we initialised?
1576 BNE %99lb_init ;Yes -- return
1577 ORR R14,R14,#wsFlag__inited ;We are initialised now
1578 STR R14,ws__flags ;Store back modified flags
1579
1580 ; --- Return to caller ---
1581
1582 99lb_init LDMFD R13!,{R12,PC}^ ;Return to caller
1583
1584 LTORG
1585
1586 lb__wSpace DCD 0
1587
1588 ;----- List events ----------------------------------------------------------
1589
1590 ^ 0
1591 lbEvent_close # 1 ;Listbox has been closed
1592
1593 lbEvent_redraw # 1 ;Redraw a list item
1594 ;R1 == pointer to list item
1595 ;R2-R5 == window coords
1596 lbEvent_click # 1 ;Click/Double on listbox
1597 ;R1 == pointer to list item
1598 ;R2 == window relative y pos
1599 ;R3 == button type (10)
1600 lbEvent_menu # 1 ;Menu click
1601 ;R1 == pointer to list item
1602 ;R2 == window relative y pos
1603 ;R3 == button type (10)
1604 lbEvent_drag # 1 ;Drag on listbox
1605 ;R1 == pointer to list item
1606 ;R2 == window relative y pos
1607 ;R3 == button type (10)
1608 lbEvent_help # 1 ;R1 == pointer to list item
1609 lbEvent_drop # 1 ;R1 == pointer to list item
1610 ;R2 == filetype
1611 ;R3 == pointer to filename
1612 ;R4 == estimated file size
1613 ;R5 == subreason cde
1614
1615 ^ 0
1616 lbDrop_load # 1
1617 lbDrop_save # 1
1618
1619 ;----- Workspace layout -----------------------------------------------------
1620
1621 ; --- listbox block descriptor ---
1622
1623 ^ 0
1624
1625 lb_itemToIndex # 4 ;Item to index routine
1626 lb_indexToItem # 4 ;Index to item routine
1627 lb_enumerate # 4 ;Enumeration function
1628 lb_items # 4 ;Function to return items
1629 lb_setFlags # 4 ;Function to set/read flags
1630
1631 ; --- listbox individual layout ---
1632
1633 ^ 0
1634
1635 lb__descriptor # 4 ;Pointer to descriptor above
1636 lb__list # 4 ;The list itself
1637 lb__widthFun # 4 ;Function to return width
1638 lb__iHeight # 4 ;Height of each item
1639 lb__pWHandle # 4 ;Parent window handle
1640 lb__pIHandle # 4 ;Parent icon handle
1641 lb__handler # 4 ;The handler function
1642 lb__R10 # 4 ;The R10 value to pass
1643 lb__R12 # 4 ;The R12 value to pass
1644 lb__width # 4 ;Overall box width
1645 lb__height # 4 ;Overall box height
1646 lb__flags # 4 ;Listbox flags
1647 lb__wHandle # 4 ;The listbox window handle
1648 lb__maxWidth # 4 ;The maximum item width
1649 lb__size # 4 ;Size of this structure
1650
1651 ; --- Main workspace ---
1652
1653 ^ 0,R12
1654
1655 ws__flags # 4 ;The flags word
1656 ws__dragItem # 4 ;Item from which drag starts
1657 ws__dragLast # 4 ;Last drag item visited
1658
1659 ws__size EQU {VAR}-ws__flags ;The size of the workspace
1660
1661 wsFlag__inited EQU (1<<0) ;We are initialised
1662
1663 AREA |Sapphire$$LibData|,CODE,READONLY
1664
1665 DCD ws__size
1666 DCD lb__wSpace
1667 DCD 0
1668 DCD lb_init
1669
1670 ;----- That's all, folks ----------------------------------------------------
1671
1672 END