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