4 ; Nice listbox handling routines (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 ------------------------------------------------
45 ;----- Main code ------------------------------------------------------------
47 AREA |Sapphire$$Code|,CODE,READONLY
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
59 ; On exit: R0 == listbox handle
60 ; R1 == window handle of list box
61 ; May return an error (R1 corrupted)
66 STMFD R13!,{R2,R3,R10,R14} ;Stack some registers
68 ; --- First, create the block ---
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
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
85 ; --- Calculate the minimum width and height of the box ---
87 CMP R5,#-1 ;Is this a pane listbox?
88 BNE %10lb_create ;No -- use icon then
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
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
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
114 ; --- Now create the window ---
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
136 ; --- Set up the event handler ---
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
143 ; --- Add it as a pane to the parent (if we need to) ---
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)
150 ; --- Add scroll bars if we need too ---
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
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
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
169 lb__windowDef DCD 320,256,960,768
173 DCB 7,2,7,255,3,1,12,0
180 lb__defSize EQU {PC}-lb__windowDef
182 ; --- lb__rescanSize ---
184 ; On entry: R10 == pointer to listbox
185 ; Bit 31 == don't call open the window
187 ; On exit: VS and R0 == pointer to error or
188 ; VC and R0 == window handle
190 ; Use: Scans the list, and adds/removes scroll bars if necessary
194 STMFD R13!,{R1-R10,R14} ;Stack some registers
195 BIC R10,R10,#(1<<31) ;Clear the top bit
197 ; --- First get the window state of the current window ---
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
226 ; --- Which scroll bars do we want? ---
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
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
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
244 ; --- Do we need to add/remove scroll bars? ---
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
250 ; --- Now we need to recreate the window ---
252 BIC R6,R6,#&50000000 ;No scroll bars at all
253 ORR R6,R6,R14 ;Just the ones we want please
255 ; --- Now create the new window ---
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
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
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
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
290 50 ; --- Work out the correct extents ---
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
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
303 RSB R2,R7,#0 ;y0 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
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
326 ; --- Return to caller ---
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
336 ; On entry: R0 == listbox handle
340 ; Use: Destroys the given listbox.
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
351 ; --- Remove the pane attachment ---
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
357 ; --- Remove the event handler ---
359 MOV R0,R1 ;The window handle
360 BL win_windowDeleted ;Remove the handler
362 ; --- Finally, free the block ---
364 MOV R0,R10 ;Point to the block
367 LDMFD R13!,{R0-R3,R10,PC}^ ;Return to caller
369 ; --- lb_eventHandler ---
371 ; On entry: R0 == listbox handle
372 ; R1 == handler function
373 ; R2 == R10 value to pass
374 ; R3 == R12 value to pass
378 ; Use: Registers an event handler for the given listbox.
380 EXPORT lb_eventHandler
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
390 ; --- lb__getMaxWidth ---
392 ; On entry: R10 == pointer to listbox structure
394 ; On exit: R0 == longest item width in the list
398 STMFD R13!,{R1-R7,R14} ;Stack some registers
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
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
424 ; --- lb__eventHandler ---
426 ; On entry: R0 == event type
427 ; R1 == pointer to event block
431 ; Use: Called to deal with events on the listbox window
433 lb__eventHandler ROUT
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
447 BICS PC,R14,#C_flag ;Return -- didn't understand
451 ; --- lb__dispatch ---
453 ; On entry: R0 == a list box event code
454 ; R1-R8 == arguments for the client's event handler
455 ; R10 == list box handle
457 ; On exit: CC or CS, from the event handler
459 ; Use: Sends an event to the user event handler for the list box.
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
476 ; --- lb__message ---
478 ; On entry: R0 == message type (17 or 18)
483 ; Use: Called when the listbox recieves a message
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
496 ; --- Check for mode/font changes ---
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
505 ; --- Handle a help request ---
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
513 ; --- Handle data saves and loads ---
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
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
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
535 ; --- lb__getItem ---
537 ; On entry: R1 == pointer to a mouse info block
538 ; R10 == pointer to the listbox
540 ; On exit: R1 == the item
542 ; Use: Returns the item the pointer is over
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
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
577 ; On entry: R1 == pointer to a window handle
581 ; Use: Redraws a list box, by sending redraw events to the client.
585 STMFD R13!,{R0-R9,R14} ;Save masses of registers
587 ; --- Start a redraw job ---
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
593 ; --- Do some setting up ---
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
599 ; --- Get the left and right sides set up ---
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
606 LDR R9,[R10,#lb__descriptor] ;Load his list descriptor
607 LDR R8,[R10,#lb__list] ;Find the list block
609 ; --- Work out which bits need drawing ---
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
616 MOV R5,#0 ;Top of the first item
617 MOV R1,#0 ;Start at item -1 (sort of)
619 ; --- Get items until one is visible ---
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
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
633 ; --- Now draw items until they stop being visible ---
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
639 ; --- The main plotting loop ---
641 20lb__redraw CMP R5,R6 ;Is this one visible?
642 BLE %80lb__redraw ;No -- then stop plotting
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
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
658 ; --- Fill in the rest in grey ---
660 CMP R5,R6 ;Do we really have to draw it
661 BLE %80lb__redraw ;No -- then stop plotting
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
679 ; --- Go round and get another rectangle ---
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
686 ; --- We finished at last ---
688 90lb__redraw LDMFD R13!,{R0-R9,R14} ;Unstack the registers again
689 ORRS PC,R14,#C_flag ;More redraws cause flicker
699 ; Use: Informs the user when the listbox has been closed.
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
719 STMFD R13!,{R0-R4,R14} ;Stack some registers
720 MOV R4,R1 ;Keep the block pointer
722 ; --- First, try to scroll vertically ---
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
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
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
740 ; --- Do a y scroll page down ---
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
751 ; --- Do a y scroll line down ---
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
762 ; --- Do a y scroll page up ---
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
773 ; --- Do a y scroll line up ---
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
782 ; --- Now do the x scrolling ---
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
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
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
807 ; --- lb_plotString ---
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
816 ; Use: Plots a list item consisting of a single string. It assumes
817 ; the default selection model.
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
848 ; On entry: R0 == listbox handle
850 ; On exit: May return an error
852 ; Use: Updates the entire listbox prettily
857 STMFD R13!,{R0-R4,R10,R14} ;Stack sonme registers
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
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
872 SWI Wimp_ForceRedraw ;Force a redraw
874 LDMFD R13!,{R0-R4,R10,PC}^ ;Return to caller
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
882 ; --- lb_updateItem ---
884 ; On entry: R0 == list box handle
885 ; R1 == list item handle
889 ; Use: Redraws a list item to reflect a change in its state.
894 STMFD R13!,{R0-R5,R10,R14} ;Save a load of registers
896 ; --- Find the item's index ---
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
904 ; --- Now set up the update block ---
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
919 ; --- Update the item ---
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
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
934 ; --- Tidy up and go home again ---
936 90lb_updateItem ADD R13,R13,#44 ;Restore the stack pointer
937 LDMFD R13!,{R0-R5,R10,PC}^ ;And return to the caller
943 ; On entry: R0 == listbox handle
945 ; R2 == 0 to unselect, 1 to select, or 2 to toggle
949 ; Use: Selects or deselects a listbox item, nicely and without
955 CMP R1,#0 ;Is there actually an item?
956 MOVEQS PC,R14 ;No -- then do nothing here
958 STMFD R13!,{R0-R5,R10,R14} ;Save some registers away
959 MOV R10,R0 ;Get the listbox handle
961 ; --- Read the current flags ---
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
971 ; --- Work out new flags ---
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
981 ; --- Set the new flags ---
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
992 ; --- lb_isSelected ---
994 ; On entry: R0 == listbox handle
997 ; On exit: CS if item is selected, else CC
999 ; Use: Informs you whether an item is selected.
1001 EXPORT lb_isSelected
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
1022 ; On entry: R1 == pointer to event block
1026 ; Use: Dispatches click events on the list box
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
1034 BL lb__getItem ;Get item pointer is over
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
1045 ; --- Deal with menu clicks ---
1047 MOV R0,#lbEvent_menu ;The event type
1048 BL lb__dispatch ;Dispatch the event
1049 B %99lb__click ;And return to caller
1051 ; --- Click or double click on an item ---
1053 10 MOV R0,#lbEvent_click ;The event type
1054 BL lb__dispatch ;Dispatch the event
1055 B %99lb__click ;And return to caller
1057 ; --- There was a drag event ---
1059 20 MOV R0,#lbEvent_drag ;The event type
1060 BL lb__dispatch ;Dispatch the event
1061 B %99lb__click ;And return to caller
1063 99 LDMFD R13!,{R0-R4,R9,PC}^ ;Return to caller
1067 ; --- lb_clearSelection ---
1069 ; On entry: R0 == listbox handle
1070 ; R1 == item handle of item to ignore (or 0 for none)
1074 ; Use: Deselects all items in the listbox.
1076 EXPORT lb_clearSelection
1077 lb_clearSelection ROUT
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
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
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
1100 90 LDMFD R13!,{R0-R6,R10,PC}^ ;Return to caller
1106 ; On entry: R0 == listbox handle
1107 ; R1 == pointer to list item
1108 ; R3 == mouse button status
1112 ; Use: Provides a default action for clicking on an item in a
1115 ; Only one selection is possible at any one time.
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
1133 ; On entry: R0 == listbox handle
1134 ; R1 == pointer to list item
1135 ; R3 == mouse button status
1139 ; Use: Provides a default action for clicking on an item in a
1142 ; The multiple selection model is used.
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
1162 ; --- lb__idleHandler ---
1164 ; On entry: R10 == listbox handle
1165 ; R12 == workspace pointer ;
1168 ; Use: Called on NULL events during a drag
1170 lb__idleHandler ROUT
1172 STMFD R13!,{R0-R9,R14} ;Stack some registers
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
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
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
1202 ; --- Find minimum and maximum values ---
1205 MOVGT R7,R6 ;Yes == R0:=R2
1207 MOVGT R7,R3 ;Yes == R0:=R3
1210 MOVLT R8,R6 ;Yes == R0:=R2
1212 MOVLT R8,R3 ;Yes == R0:=R3
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
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
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
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
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
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
1255 30 CMP R4,R8 ;Are we at the end?
1256 BGT %50lb__idleHandler ;Yes -- jump out of loop
1258 ; --- Redraw the item if we need to ---
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
1285 40 LDMFD R13!,{R0-R4} ;Restore registers
1286 B %00lb__idleHandler ;Keep going round
1288 50 LDMFD R13!,{R12} ;Get R12 back again
1289 STR R5,ws__dragLast ;Store last item visited
1291 ; --- Scroll the window nicely ---
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
1307 99 ADD R13,R13,#56 ;Reclaim the stack
1308 99 LDMFD R13!,{R0-R9,PC}^ ;Return to caller
1312 ; --- lb__unknownHandler ---
1314 ; On entry: R0 == event type
1316 ; R10 == listbox handle
1317 ; R12 == workspace pointer
1321 ; Use: Called when the drag is ended
1324 lb__unknownHandler ROUT
1326 CMP R0,#7 ;Are we interested?
1327 MOVNES PC,R14 ;No -- return PDQ
1329 STMFD R13!,{R0-R4,R14} ;Stack some registers
1331 ; --- First get rid of the idle claimer ---
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
1339 ; --- Now this unknown handler ---
1341 ADR R0,lb__unknownHandler ;Call this routine
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
1347 ; --- Make temporary selections permanant ---
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
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
1365 99 LDMFD R13!,{R0-R4,PC}^ ;Return to caller
1371 ; On entry: R0 == listbox handle
1372 ; R1 == pointer to list item
1373 ; R3 == mouse button status
1377 ; Use: Starts a drag operation to allow for easy multiple
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
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
1397 ; --- First we must start the drag box ---
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
1413 ; --- Set up the idle event handler ---
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
1421 ; --- Set up the unknown handler ---
1423 ADR R0,lb__unknownHandler ;Call this routine
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
1429 ; --- Now return to the caller ---
1431 ADD R13,R13,#40 ;Reclaim the stack
1432 LDMFD R13!,{R0-R3,R10,R12,PC}^ ;Return to caller
1436 ; --- lb_inserted ---
1438 ; On entry: R0 == pointer to the listbox
1439 ; R1 == pointer to the new item
1443 ; Use: Informs the listbox that an item has been inserted,
1444 ; and causes a flicker free insert to occur if possible.
1449 STMFD R13!,{R0-R8,R10,R14} ;Stack some registers
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
1459 ; --- Now do the block copy ---
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
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
1482 ; --- Finally, update the new item ---
1484 MOV R0,R10 ;Point to the listbox
1485 MOV R1,R7 ;Put item pointer in R1
1486 BL lb_updateItem ;Update the item
1488 99lb_inserted LDMFD R13!,{R0-R8,R10,PC}^ ;Return to caller
1492 ; --- lb_removed ---
1494 ; On entry: R0 == pointer to the listbox
1495 ; R1 == index of item removed
1499 ; Use: Informs the listbox that an item has been removed, and
1500 ; causes a flicker free remove to occur, if possible.
1505 STMFD R13!,{R0-R8,R10,R14} ;Stack some registers
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
1515 ; --- Now do the block copy ---
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
1538 99lb_removed LDMFD R13!,{R0-R8,R10,PC}^ ;Return to caller
1544 ; On entry: R0 == listbox handle
1546 ; On exit: R0 == window handle
1548 ; Use: Returns the window handle of the listbox
1553 LDR R0,[R0,#lb__wHandle] ;Load the window handle
1554 MOVS PC,R14 ;Return to caller
1564 ; Use: Initialises the listbox unit.
1569 STMFD R13!,{R12,R14} ;Stack some registers
1570 WSPACE lb__wSpace ;Locate my workspace
1572 ; --- Ensure that we are not already initialised ---
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
1580 ; --- Return to caller ---
1582 99lb_init LDMFD R13!,{R12,PC}^ ;Return to caller
1588 ;----- List events ----------------------------------------------------------
1591 lbEvent_close # 1 ;Listbox has been closed
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
1611 ;R3 == pointer to filename
1612 ;R4 == estimated file size
1613 ;R5 == subreason cde
1619 ;----- Workspace layout -----------------------------------------------------
1621 ; --- listbox block descriptor ---
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
1631 ; --- listbox individual layout ---
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
1651 ; --- Main workspace ---
1655 ws__flags # 4 ;The flags word
1656 ws__dragItem # 4 ;Item from which drag starts
1657 ws__dragLast # 4 ;Last drag item visited
1659 ws__size EQU {VAR}-ws__flags ;The size of the workspace
1661 wsFlag__inited EQU (1<<0) ;We are initialised
1663 AREA |Sapphire$$LibData|,CODE,READONLY
1670 ;----- That's all, folks ----------------------------------------------------