Initial revision
[ssr] / StraySrc / Libraries / Sapphire / s / viewer
1 ;
2 ; viewer.s
3 ;
4 ; Filer-like windows with re-arranging icons (MDW)
5 ;
6 ; © 1995-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 GET libs:stream
33
34 ;----- External dependencies ------------------------------------------------
35
36 GET sapphire:akbd
37 GET sapphire:alloc
38 GET sapphire:divide
39 GET sapphire:drag
40 GET sapphire:fastMove
41 GET sapphire:msgs
42 GET sapphire:sapphire
43 GET sapphire:screen
44 GET sapphire:wimp
45 GET sapphire:win
46 GET sapphire:winUtils
47
48 ;----- Macros ---------------------------------------------------------------
49
50 MACRO
51 $label MSGB $msg,$branch
52 $label DCD $msg
53 B $branch
54 MEND
55
56 ;----- Main code ------------------------------------------------------------
57
58 AREA |Sapphire$$Code|,CODE,READONLY
59
60 ;----- Creating and deleting viewers ----------------------------------------
61
62 ; --- viewer_create ---
63 ;
64 ; On entry: R0 == pointer to a viewer definition block
65 ; R1 == pointer to a list
66 ; R2 == sprite area for window
67 ;
68 ; On exit: R0 == viewer handle
69 ; May return an error
70 ;
71 ; Use: Creates a viewer window. The viewer definition block
72 ; contains various interesting bits of information about the
73 ; viewer which are likely to be known at assembly time:
74 ;
75 ; (word) address of a list manager definition block
76 ; (word) address of a shape handler function (or 0)
77 ; (word) standard width of icons
78 ; (word) standard height of icons
79 ; (string) banner text message tag, or empty
80 ;
81 ; The shape function is used to allow viewer icons to have a
82 ; non-rectangular shape. The function is called with a reason
83 ; code in R0; entry and exit conditions depend on this:
84 ;
85 ; vwShape_size
86 ; On entry
87 ; R1 == pointer to list item
88 ; R2 == standard width of icon
89 ; R3 == standard height of icon
90 ;
91 ; On exit
92 ; R2 == width of this icon
93 ; R3 == height of this icon
94 ;
95 ; Use
96 ; This routine is used to find the actual size of an icon.
97 ; The icons are aligned on a grid according to the largest
98 ; one: this routine is used to find out which one that is.
99 ;
100 ; vwShape_intersects
101 ; On entry
102 ; R1 == pointer to list item
103 ; R2 == address of bounding box of this icon
104 ; R3 == address of bounding box to compare
105 ;
106 ; On exit
107 ; CS if boxes intersect, else CC
108 ;
109 ; Use
110 ; For detecting mouse clicks etc. on an icon. viewer has
111 ; already ensured that the box in R3 intersects with the
112 ; bounding box, so for rectangular icons, you can just return
113 ; with C set always. This entry is provided so that you
114 ; can check against the sprite and text of a text+sprite
115 ; icon separately.
116 ;
117 ; More reason codes may be added later; it will always be
118 ; sensible to return immediately preserving all registers and
119 ; flags.
120
121 EXPORT viewer_create
122 viewer_create ROUT
123
124 STMFD R13!,{R1-R5,R10,R14} ;Save some registers
125
126 ; --- Move arguments into other registers ---
127
128 MOV R5,R0 ;Look after block def
129 MOV R4,R2 ;And the sprite area
130
131 ; --- Allocate a viewer block ---
132
133 MOV R0,#vw__size ;Get the block size
134 BL alloc ;Allocate the memory
135 BLCS alloc_error ;If it failed, get error
136 BCS %99viewer_create ;And return to caller
137 MOV R10,R0 ;Look after the pointer
138
139 ; --- Fill in bits of the block ---
140
141 STR R1,[R10,#vw__list] ;Store the list address
142 LDMIA R5!,{R0-R3} ;Load regs from def block
143 STR R0,[R10,#vw__listDef] ;Store list definition addr
144 CMP R1,#0 ;Is the shape function 0?
145 ADREQ R1,vw__dummyShape ;Yes -- use default one
146 STR R1,[R10,#vw__shape] ;Store that away nicely
147 ADD R14,R10,#vw__stdDimens ;Point to standard icon sz
148 STMIA R14,{R2,R3} ;Store them away nicely
149 LDRB R0,[R5,#0] ;Load first byte of banner
150 CMP R0,#0 ;Is it actually defined?
151 MOVNE R0,R5 ;Yes -- point to it then
152 BLNE msgs_lookup ;And translate the tag
153 STR R0,[R10,#vw__banner] ;Store that away nicely
154
155 ; --- Now create a window ---
156
157 MOV R0,R11 ;Copy definition to scratch
158 ADR R1,vw__windDef ;Point to my definition
159 MOV R2,#88 ;Size of window definition
160 BL fastMove ;Copy the data over
161
162 STR R4,[R11,#64] ;Store caller's sprite area
163 ADD R14,R10,#vw__title ;Point to title buffer
164 STR R14,[R11,#72] ;Save this in window block
165 MOV R1,R11 ;Point to window definition
166 SWI XWimp_CreateWindow ;Try to do that then
167 BVS %98viewer_create ;If it failed, tidy up
168 STR R0,[R10,#vw__window] ;Save the window handle
169
170 ; --- Set up the event handler ---
171
172 ADR R1,vw__events ;Point to event handler
173 MOV R2,R10 ;Use viewer handle as R10
174 MOV R3,R12 ;Pass workspace in R12 (*)
175 BL win_eventHandler ;Set up the event handler
176 BVS %97viewer_create ;If it failed, tidy up
177
178 ; --- Fix up rest of viewer block ---
179
180 MOV R14,#0 ;No handler defined yet
181 STR R14,[R10,#vw__handler] ;Save that in my block
182 STR R14,[R10,#vw__flags] ;Clear the flags too
183 STR R14,[R10,#vw__tempSel] ;No temporary selection
184
185 ; --- Now return to caller ---
186
187 MOV R0,R10 ;Get the viewer handle
188 LDMFD R13!,{R1-R5,R10,R14} ;Restore registers
189 BICS PC,R14,#V_flag ;And return to caller
190
191 ; --- Handle minor mishaps ---
192
193 97viewer_create MOV R5,R0 ;Look after error pointer
194 ADD R1,R10,#vw__window ;Point to window handle
195 SWI Wimp_DeleteWindow ;Destroy the window
196 MOV R0,R5 ;And get the error back
197
198 98viewer_create MOV R5,R0 ;Look after error pointer
199 MOV R0,R10 ;Point to viewer block
200 BL free ;Free the block up
201 MOV R0,R5 ;And get the error back
202
203 99viewer_create ADD R2,R0,#4 ;Point to error text
204 ADR R0,vw__createErr ;Point to error skeleton
205 BL msgs_error ;Translate and substitute
206 LDMFD R13!,{R1-R5,R10,R14} ;Restore registers
207 ORRS PC,R14,#V_flag ;And return the error
208
209 vw__dummyShape ORRS PC,R14,#C_flag ;Dummy shape function
210
211 vw__createErr DCD 1
212 DCB "vwCRTE",0
213
214 vw__windDef DCD 0,0,0,0
215 DCD 0,0
216 DCD 0
217 DCD &BF000002
218 DCB 7,2,7,1,3,1,12,0
219 DCD 0,0,0,0
220 DCD &1700013D
221 DCD &0000A000
222 DCD 1
223 DCW 1,0
224 DCD 0,-1,256
225 DCD 0
226
227 LTORG
228
229 ; --- viewer_destroy ---
230 ;
231 ; On entry: R0 == viewer handle
232 ;
233 ; On exit: --
234 ;
235 ; Use: Destroys a viewer, removing it from the screen etc.
236
237 EXPORT viewer_destroy
238 viewer_destroy ROUT
239
240 STMFD R13!,{R0,R1,R10,R14} ;Save some registers
241 MOV R10,R0 ;Look after the handle
242 LDR R0,[R10,#vw__window] ;Load the window handle
243 BL win_windowDeleted ;Say it's been deleted
244 ADD R1,R10,#vw__window ;Find the window handle
245 SWI Wimp_DeleteWindow ;Destroy the window
246 MOV R0,R10 ;Point to the viewer block
247 BL free ;Release the memory
248 LDMFD R13!,{R0,R1,R10,PC}^ ;And return to caller
249
250 LTORG
251
252 ;----- Opening and closing --------------------------------------------------
253
254 ; --- viewer_open ---
255 ;
256 ; On entry: R0 == viewer handle
257 ; R1 == opening style
258 ; R2,R3 == extra arguments
259 ;
260 ; On exit: --
261 ;
262 ; Use: Opens a viewer window on the screen.
263
264 EXPORT viewer_open
265 viewer_open ROUT
266
267 STMFD R13!,{R0,R1,R4,R10,R14} ;Save some registers
268 MOV R10,R0 ;Get the viewer handle
269 MOV R4,R1 ;Look after opening style
270
271 SUB R13,R13,#36 ;Make a window state block
272 LDR R14,[R10,#vw__window] ;Load the window handle
273 STR R14,[R13,#0] ;Save it in the block
274 MOV R1,R13 ;Point to the block
275 SWI Wimp_GetWindowState ;And read the window state
276
277 ; --- If window is open, skip on ---
278
279 BL vw__open ;Is the window open?
280 BCS %10viewer_open ;Yes -- skip onwards then
281
282 ; --- Open the window onto the screen ---
283
284 LDR R1,[R10,#vw__listDef] ;Find the list definition
285 LDR R0,[R10,#vw__list] ;And the list base
286 MOV R14,PC ;Set up return address
287 ADD PC,R1,#vw__items ;Find how many items
288 STR R1,[R10,#vw__icons] ;Store this away
289
290 MOV R1,R13 ;Point at window state blk
291 BL vw__tWidth ;Work out title width
292 BL vw__rescanSize ;Rescan the item size
293 BL vw__extend ;Yes -- make it big then
294 BL vw__resize ;Work out new arrangement
295 BL vw__setExtent ;Set the window's extent
296
297 ; --- Finally work out where to open it ---
298
299 10viewer_open MOV R0,R4 ;Get the opening style
300 BL winUtils_setPosition ;Set the window position
301 BL vw__openWindow ;Open the window there
302 ADD R13,R13,#36 ;Reclaim the stack space
303 LDR R14,[R10,#vw__flags] ;Load the flags word
304 ORR R14,R14,#vwFlag__opened ;We've now opened it
305 STR R14,[R10,#vw__flags] ;Store the flags back
306 LDMFD R13!,{R0,R1,R4,R10,PC}^ ;And return to caller
307
308 LTORG
309
310 ; --- viewer_close ---
311 ;
312 ; On entry: R0 == viewer handle
313 ;
314 ; On exit: --
315 ;
316 ; Use: Closes a viewer window.
317
318 EXPORT viewer_close
319 viewer_close ROUT
320
321 STMFD R13!,{R0,R1,R14} ;Save some registers
322 ADD R1,R0,#vw__window ;Find the window handle
323 SWI Wimp_CloseWindow ;Close the window
324 LDMFD R13!,{R0,R1,PC}^ ;And return to caller
325
326 LTORG
327
328 ;----- Event handling -------------------------------------------------------
329
330 ; --- viewer_eventHandler ---
331 ;
332 ; On entry: R0 == viewer handle
333 ; R1 == pointer to event handler
334 ; R2 == value to pass in R10
335 ; R3 == value to pass in R12
336 ;
337 ; On exit: R1-R3 == old values
338 ;
339 ; Use: Sets up the event handle for the viewer.
340
341 EXPORT viewer_eventHandler
342 viewer_eventHandler ROUT
343
344 STMFD R13!,{R4-R6,R14} ;Save some registers
345 ADD R14,R0,#vw__handler ;Point to handler block
346 LDMIA R14,{R4-R6} ;Load the old handler
347 STMIA R14,{R1-R3} ;Save the new one
348 MOV R1,R4 ;Transfer information over
349 MOV R2,R5 ;All of it, don't let it
350 MOV R3,R6 ;Get away!
351 LDMFD R13!,{R4-R6,PC}^ ;And return to caller
352
353 LTORG
354
355 ; --- vw__events ---
356 ;
357 ; On entry: R0 == event code
358 ; R1 == pointer to event block
359 ;
360 ; On exit: CS if handled, else CC
361 ;
362 ; Use: Handles events for a viewer window.
363
364 vw__events ROUT
365
366 CMP R0,#17 ;Is this a message?
367 CMPNE R0,#18 ;Check *both* types
368 BEQ %10vw__events ;Yes -- handle them
369 CMP R0,#9 ;Is the event interesting?
370 ADDCC PC,PC,R0,LSL #2 ;Yes -- dispatch it then
371 MOVS PC,R14 ;Otherwise ignore it
372
373 ; --- Branch table ---
374
375 MOVS PC,R14
376 B vw__evRedraw
377 B vw__evOpen
378 B vw__evClose
379 MOVS PC,R14
380 MOVS PC,R14
381 B vw__evMouse
382 MOVS PC,R14
383 B vw__evKey
384
385 ; --- Handle messages ---
386 ;
387 ; This is a little odd, in the interests of expandability.
388
389 10vw__events STMFD R13!,{R2-R4,R14} ;Save some registers
390 LDR R2,[R1,#16] ;Load the message code
391 ADR R3,vw__msgTable ;Point to the message table
392 00 LDR R4,[R3],#8 ;Load the message code
393 CMP R4,R2 ;Do I recognise this event?
394 SUBEQ R3,R3,#4 ;Yes -- point to branch instr
395 STREQ R3,[R13,#12] ;Store as return address
396 CMPNE R4,#-1 ;Is it the end of the list?
397 BNE %b00 ;No -- keep looping then
398 LDMFD R13!,{R2-R4,PC}^ ;Call the routine
399
400 ; --- Message table ---
401
402 vw__msgTable MSGB &1,vw__mDataSave
403 MSGB &3,vw__mDataLoad
404 MSGB &502,vw__mHelpRq
405 MSGB &400CF,vw__mFontChnge
406 DCD -1,-1
407
408 LTORG
409
410 ; --- vw__dispatch ---
411 ;
412 ; On entry: R0 == event code
413 ; R1-R5 set up for event
414 ;
415 ; On exit: CS or CC according to event handler
416 ;
417 ; Use: Dispatches an event to the user's handler.
418
419 EXPORT vw__dispatch
420 vw__dispatch ROUT
421
422 STMFD R13!,{R8-R10,R12,R14} ;Save some registers
423 ADD R14,R10,#vw__handler ;Find the handler routine
424 MOV R9,R10 ;Pass viewer handle in R9
425 LDMIA R14,{R8,R10,R12} ;Load the things out
426 ADDS R0,R0,#0 ;Clear the carry flag
427 TEQ R8,#0 ;Is there a routine?
428 MOVNE R14,PC ;Yes -- set up return addr
429 MOVNE PC,R8 ;And call the routine
430 LDMFD R13!,{R8-R10,R12,R14} ;Restore registers
431 ORRCSS PC,R14,#C_flag ;If it set C, we do too
432 BICCCS PC,R14,#C_flag ;Otherwise we clear it
433
434 LTORG
435
436 ; --- vw_evRedraw ---
437 ;
438 ; On entry: R1 == pointer to window handle in block
439 ;
440 ; On exit: CS
441 ;
442 ; Use: Redraws a viewer window.
443
444 vw__evRedraw ROUT
445
446 STMFD R13!,{R0-R7,R14} ;Save some registers
447 SWI Wimp_RedrawWindow ;Start the redraw job
448 CMP R0,#0 ;Is this the end yet?
449 BEQ %90vw__evRedraw ;Yes -- do nothing then
450
451 ; --- Find the window origin ---
452
453 MOV R7,R1 ;Remember the block pointer
454 LDR R2,[R7,#4] ;Load the left hand side
455 ADD R14,R7,#16 ;Point to top and scroll pos
456 LDMIA R14,{R3-R5} ;Load those positions out
457 SUB R6,R3,R5 ;Find the top position
458 SUB R5,R2,R4 ;And the left side
459 SUB R13,R13,#32 ;Space for rectangle block
460
461 ; --- The main redraw loop ---
462 ;
463 ; First of all, handle the banner.
464
465 10vw__evRedraw LDR R14,[R10,#vw__banner] ;Load the banner address
466 CMP R14,#0 ;Is there one defined?
467 BEQ %f00 ;No -- skip ahead then
468
469 ; --- See if we need to do this ---
470
471 LDR R14,[R7,#28+16] ;Load the top coordinate
472 CMP R14,R6 ;Is this above the line?
473 BLT %f00 ;No -- don't bother then
474
475 ; --- Render the banner's background ---
476
477 MOV R0,#3 ;Get the banner colour
478 SWI Wimp_SetColour ;Set this as the colour
479
480 MOV R0,#4 ;Move the graphics cursor
481 LDR R1,[R7,#28+0] ;Find left side of window
482 MOV R2,R6 ;Baseline on window origin
483 SWI OS_Plot ;Do the cursor move
484 MOV R0,#101 ;Rectangle fill absolute
485 LDR R1,[R7,#28+8] ;Load right side of window
486 ADD R2,R6,#vw__banHeight ;Get the banner height
487 SWI OS_Plot ;Do that too
488
489 ; --- Now plot the banner text ---
490
491 MOV R14,R13 ;Point at the stack block
492
493 MOV R0,#28 ;We have an odd left side
494 MOV R1,#0 ;Baseline is along origin
495 LDR R2,[R10,#vw__fixedWidth] ;Load width of the banner
496 MOV R3,#vw__banHeight ;Get the banner's height
497 STMIA R14!,{R0-R3} ;Save the coordinates
498
499 LDR R0,=&37000131 ;Get the icon flags word
500 LDR R1,[R10,#vw__banner] ;Load the banner pointer
501 MOV R2,#-1 ;No validation string
502 MOV R3,#1 ;Bogus string length
503 STMIA R14!,{R0-R3} ;Save the other bits
504
505 MOV R1,R13 ;Point to the block
506 SWI Wimp_PlotIcon ;Plot the text as an icon
507
508 ; --- Now alter the graphics rectangle ---
509
510 00 ADD R14,R7,#28 ;Find the clipping rectangle
511 LDMIA R14,{R0-R3} ;Load the rectangle out
512 SUB R0,R0,R5 ;Convert to window coords
513 SUB R1,R1,R6 ;This isn't terribly hard
514 SUB R2,R2,R5 ;Just subtract origin posn
515 SUB R3,R3,R6 ;For all the coordinates
516 STMIA R14,{R0-R3} ;Store those in the block
517
518 ; --- Plot each interesting icon ---
519
520 MOV R0,#vwEvent_redraw ;Say this is a redraw event
521 MOV R1,#0 ;Start at the beginning
522 MOV R2,R13 ;Use my stack buffer
523 ADD R3,R7,#28 ;Point to the clip block
524 00 BL vw__enum ;Get next icon ready
525 BCC %f00 ;If no more, skip onwards
526 BL vw__intSimple ;Do quick clipping check
527 BLCS vw__dispatch ;Yes -- package off the event
528 B %b00 ;Loop round for the rest
529
530 ; --- Finish off the redraw loop ---
531
532 00 MOV R1,R7 ;Point at the event block
533 BL drag_redraw ;Draw the drag box if reqd
534 SWI Wimp_GetRectangle ;Get another rectangle
535 CMP R0,#0 ;Is there more to do?
536 BNE %10vw__evRedraw ;Yes -- loop back to do it
537
538 ADD R13,R13,#32 ;Restore the stack pointer
539
540 90vw__evRedraw LDMFD R13!,{R0-R7,R14} ;Unstack the registers
541 ORRS PC,R14,#C_flag ;And *claim the event*
542
543 LTORG
544
545 ; --- vw__evOpen ---
546 ;
547 ; On entry: R1 == pointer to an open-window block
548 ;
549 ; On exit: CS
550 ;
551 ; Use: Opens a viewer window.
552
553 vw__evOpen ROUT
554
555 STMFD R13!,{R0,R14} ;Save some registers
556 MOV R14,#0 ;Force horizontal scroll
557 STR R14,[R1,#20] ;To stop it looking odd
558 BL screen_justChangedMode ;Just had a mode change?
559 BCS %50vw__evOpen ;Yes -- handle that
560
561 ; --- Just rescan the size like nice people ---
562
563 BL vw__resize ;Modify the arrangement
564 BLCS vw__setExtent ;Maybe modify the extent too
565 BLCS vw__refresh ;If so, force a redraw
566 BL vw__openWindow ;Whatever, open the window
567 LDMFD R13!,{R0,R14} ;Restore the registers
568 ORRS PC,R14,#C_flag ;And claim the event
569
570 ; --- Just changed mode -- anything could have happened ---
571
572 50vw__evOpen BL vw__tWidth ;Rescan the title width
573 BL vw__rescanSize ;Rescan the icon sizes
574 BL vw__resize ;Rearrange the icons
575 BL vw__setExtent ;Rework the extent
576 BL vw__refresh ;Redraw the work area
577 BL vw__openWindow ;And reopen the window
578 LDMFD R13!,{R0,R14} ;Restore the registers
579 ORRS PC,R14,#C_flag ;And claim the event
580
581 LTORG
582
583 ; --- vw__evClose ---
584 ;
585 ; On entry: R1 == pointer to block
586 ;
587 ; On exit: CC or CS
588 ;
589 ; Use: Handles a close request for a viewer,
590
591 vw__evClose ROUT
592
593 STMFD R13!,{R0,R14} ;Save some registers
594 MOV R0,#vwEvent_close ;Get the event code
595 BL vw__dispatch ;Send it to the user
596 LDMFD R13!,{R0,PC} ;And return this state
597
598 LTORG
599
600 ; --- vw__evMouse ---
601 ;
602 ; On entry: R1 == pointer to pointer info block
603 ;
604 ; On exit: CS
605 ;
606 ; Use: Handles a mouse click on the viewer.
607
608 vw__evMouse ROUT
609
610 STMFD R13!,{R0-R4,R14} ;Save some registers
611 MOV R4,R1 ;Look after this pointer
612 LDMIA R4,{R2,R3} ;Load the coordinates out
613 BL vw__whichIcon ;Which icon is that?
614
615 LDR R2,[R4,#8] ;Load the button state
616 TST R2,#&002 ;Is this a menu click?
617 MOVNE R0,#vwEvent_menu ;Yes -- pass that event
618 TST R2,#&005 ;Another normal click?
619 MOVNE R0,#vwEvent_double ;Yes -- that's a double
620 TST R2,#&050 ;Is it a drag?
621 MOVNE R0,#vwEvent_drag ;Yes -- use that event then
622 TST R2,#&500 ;Or a normal click?
623 MOVNE R0,#vwEvent_click ;Yes -- that's a real one
624 BL vw__dispatch ;Sent the event on
625 LDMFD R13!,{R0-R4,R14} ;Save some registers
626 ORRS PC,R14,#C_flag ;We dealt with it
627
628 LTORG
629
630 ; --- vw__evKey ---
631 ;
632 ; On entry: R1 == pointer to caret info block
633 ;
634 ; On exit: CC if unclaimed, else CS
635 ;
636 ; Use: Handles a keypress while the viewer has the input focus.
637
638 vw__evKey ROUT
639
640 STMFD R13!,{R0,R1,R14} ;Save some registers
641 LDR R0,[R1,#24] ;Load the character code
642 BL akbd_translate ;Try translating the key
643 MOV R1,R0 ;Put this back in R1
644 MOV R0,#vwEvent_key ;Get the event code
645 BL vw__dispatch ;Dispatch the event
646 LDMFD R13!,{R0,R1,R14} ;Restore registers
647 ORRCSS PC,R14,#C_flag ;Claim if he claimed it
648 BICCCS PC,R14,#C_flag ;Don't claim if he didn't
649
650 LTORG
651
652 ; --- vw__mDataSave ---
653 ;
654 ; On entry: R0 == message code
655 ; R1 == pointer to message block
656 ;
657 ; On exit: --
658 ;
659 ; Use: Handles a file dropped on the viewer.
660
661 vw__mDataSave ROUT
662
663 STMFD R13!,{R0-R4,R14} ;Save some registers
664 MOV R4,#vwDrop_save ;Say it's a save event
665 ADD R3,R1,#44 ;Point to the filename
666 LDR R2,[R1,#36] ;Load the estimated size
667 LDR R1,[R1,#40] ;And the filetype
668 MOV R0,#vwEvent_drop ;Get the event code
669 BL vw__dispatch ;And send it to the client
670 LDMFD R13!,{R0-R4,PC}^ ;And return to caller
671
672 LTORG
673
674 ; --- vw__mDataLoad ---
675 ;
676 ; On entry: R0 == message code
677 ; R1 == pointer to message block
678 ;
679 ; On exit: --
680 ;
681 ; Use: Handles a file dropped on the viewer.
682
683 vw__mDataLoad ROUT
684
685 STMFD R13!,{R0-R4,R14} ;Save some registers
686 MOV R4,#vwDrop_load ;Say it's a load event
687 ADD R3,R1,#44 ;Point to the filename
688 LDR R2,[R1,#36] ;Load the estimated size
689 LDR R1,[R1,#40] ;And the filetype
690 MOV R0,#vwEvent_drop ;Get the event code
691 BL vw__dispatch ;And send it to the client
692 LDMFD R13!,{R0-R4,PC}^ ;And return to caller
693
694 LTORG
695
696 ; --- vw__mHelpRq ---
697 ;
698 ; On entry: R0 == message code
699 ; R1 == pointer to message block
700 ;
701 ; On exit: --
702 ;
703 ; Use: Handles a help request for the viewer.
704
705 vw__mHelpRq ROUT
706
707 STMFD R13!,{R0-R3,R14} ;Save some registers
708 ADD R14,R1,#20 ;Find the mouse position
709 LDMIA R14,{R2,R3} ;Load the coordinates
710 BL vw__whichIcon ;Find the icon pointed at
711 MOV R0,#vwEvent_help ;It's a help request
712 BL vw__dispatch ;Send it to the client
713 LDMFD R13!,{R0-R3,PC}^ ;And return to caller
714
715 LTORG
716
717 ; --- vw__mFontChnge ---
718 ;
719 ; On entry: R0 == message code
720 ; R1 == pointer to message block
721 ;
722 ; On exit: --
723 ;
724 ; Use: Handles font changed events for the viewer.
725
726 vw__mFontChnge ROUT
727
728 STMFD R13!,{R0-R4,R14} ;Save some registers
729 SUB R13,R13,#36 ;Make a window state block
730 LDR R14,[R10,#vw__window] ;Load viewer's window handle
731 STR R14,[R13,#0] ;Store it in the block
732 MOV R1,R13 ;Point to this block
733 SWI Wimp_GetWindowState ;Read the window information
734 BL vw__tWidth ;Rescan the title width
735 BL vw__rescanSize ;Rescan the icon sizes
736 BL vw__resize ;Rearrange the icons
737 BL vw__setExtent ;Rework the extent
738 BL vw__refresh ;Redraw the work area
739 BL vw__openWindow ;And reopen the window
740 ADD R13,R13,#36 ;Restore the stack pointer
741 LDMFD R13!,{R0-R4,PC}^ ;Return to caller
742
743 LTORG
744
745 ;----- Icon position handling -----------------------------------------------
746
747 ; --- vw__callShape ---
748 ;
749 ; On entry: R0 == reason code
750 ; R1-R? == other arguments
751 ; R10 == pointer to viewer block
752 ;
753 ; On exit: R0-R? and C returned from shape function
754 ;
755 ; Use: Calls a shape function and returns the result.
756
757 EXPORT vw__callShape
758 vw__callShape ROUT
759
760 STMFD R13!,{R8-R10,R12,R14} ;Save some registers
761 LDR R8,[R10,#vw__shape] ;Load the shape function addr
762 MOV R9,R10 ;Point to the viewer block
763 ADD R14,R10,#vw__handler+4 ;Find owner's R10 and R12
764 LDMIA R14,{R10,R12} ;Load them out nicely too
765 CMP R0,R0 ;Set the C flag on entry
766 MOV R14,PC ;Set up the return address
767 MOV PC,R8 ;Call the shape function
768 LDMFD R13!,{R8-R10,R12,R14} ;Restore registers
769 ORRCSS PC,R14,#C_flag ;If it set C, return C set
770 BICCCS PC,R14,#C_flag ;Otherwise return C clear
771
772 LTORG
773
774 ; --- vw__whichIcon ---
775 ;
776 ; On entry: R2,R3 == mouse coordinates (screen relative)
777 ; R10 == pointer to viewer block
778 ;
779 ; On exit: R1 == icon beneath the mouse pointer
780 ;
781 ; Use: Works out which icon the user is pointing at, should this be
782 ; interesting.
783
784 vw__whichIcon ROUT
785
786 STMFD R13!,{R0,R2-R6,R14} ;Save lots of registers
787
788 ; --- Find the window's state ---
789
790 SUB R13,R13,#36 ;Drop the stack to make a blk
791 LDR R14,[R10,#vw__window] ;Get the window handle
792 STR R14,[R13,#0] ;Store that in the block
793 MOV R1,R13 ;Point to the block
794 SWI Wimp_GetWindowState ;Read the window state
795
796 LDR R0,[R13,#4] ;Load the left hand side
797 ADD R14,R13,#16 ;Point to the top edge
798 LDMIA R14,{R4-R6} ;Load those values out
799 SUB R5,R0,R5 ;Work out x origin position
800 SUB R6,R4,R6 ;And the y origin position
801
802 ; --- Find the click position ---
803
804 SUB R2,R2,R5 ;Translate click coordinates
805 SUB R3,R3,R6 ;Do that nicely
806 MOV R14,R13 ;Point to my nice block
807 STMIA R14!,{R2,R3} ;Save coordinates away
808 STMIA R14!,{R2,R3} ;And do it again
809
810 ; --- Now do the enumeration ---
811
812 MOV R1,#0 ;Start at the beginning
813 ADD R2,R13,#16 ;Point to spare bit of block
814 MOV R3,R13 ;Point to my coordinates
815 BL vw__withinBox ;Try to find a match
816 MOVCC R1,#0 ;No match -- no icon
817 ADD R13,R13,#36 ;Recover stack space
818 LDMFD R13!,{R0,R2-R6,PC}^ ;And return to caller
819
820 LTORG
821
822 ; --- vw__rescanSize ---
823 ;
824 ; On entry: R10 == pointer to viewer block
825 ;
826 ; On exit: --
827 ;
828 ; Use: Recalculates the sizes of icons in the viewer.
829
830 vw__rescanSize ROUT
831
832 STMFD R13!,{R0-R7,R14} ;Save some registers
833
834 ; --- Set up for the loop ---
835
836 LDR R6,[R10,#vw__listDef] ;Find the list block
837 MOV R1,#0 ;No item found yet
838 ADD R7,R10,#vw__stdDimens ;Find standard dimensions
839 LDMIA R7,{R4,R5} ;These are minimum sizes
840
841 ; --- Now read all the items ---
842
843 00 LDR R0,[R10,#vw__list] ;Find the list head
844 MOV R2,#0 ;Match any flags
845 MOV R3,#0 ;Still match any flags
846 MOV R14,PC ;Set up return address
847 ADD PC,R6,#vw__enumerate ;Read the next list item
848 BCC %10vw__rescanSize ;If no more, skip on
849 LDMIA R7,{R2,R3} ;Load standard sizes
850 MOV R0,#vwShape_size ;Get the reason code
851 BL vw__callShape ;And call the shape function
852 CMP R4,R2 ;Now update the sizes
853 MOVCC R4,R2 ;Use the biggest on both
854 CMP R5,R3 ;Check the height too
855 MOVCC R5,R3 ;Use the biggest again
856 B %b00 ;Now loop round for more
857
858 ; --- Finished -- store result away ---
859
860 10 ADD R14,R10,#vw__iconWidth ;Find current sizes
861 STMIA R14,{R4,R5} ;Store these new sizes
862 LDMFD R13!,{R0-R7,PC}^ ;And return to caller
863
864 LTORG
865
866 ; --- vw__intSimple ---
867 ;
868 ; On entry: R2 == pointer to a box
869 ; R3 == pointer to another box
870 ;
871 ; On exit: CS if boxes intersect, else CC
872 ;
873 ; Use: Informs you whether boxes intersect. Saves lots of
874 ; registers. This is typically used before calling the
875 ; caller's shape routine to see if it's really worth it.
876
877 EXPORT vw__intSimple
878 vw__intSimple ROUT
879
880 STMFD R13!,{R0-R6,R14} ;Save some registers
881 LDMIA R3,{R4-R6,R14} ;Load second box out
882 LDMIA R2,{R0-R3} ;Load first box out
883 CMP R2,R4 ;Now do the compare
884 CMPGE R3,R5
885 CMPGE R6,R0
886 CMPGE R14,R1
887 LDMFD R13!,{R0-R6,R14} ;Restore registers
888 ORRGES PC,R14,#C_flag ;Return C set if OK
889 BICLTS PC,R14,#C_flag ;Otherwise return CC
890
891 LTORG
892
893 ; --- vw__enum ---
894 ;
895 ; On entry: R1 == 0 for first call, or item pointer
896 ; R2 == pointer to 16-byte coordinate buffer
897 ; R4 == continuation value from old call
898 ; R10 == pointer to viewer block
899 ;
900 ; On exit: CS if more icons, and
901 ; R1 == item handle
902 ; R4 == new continuation value
903 ; else CC and
904 ; R1,R4 corrupted
905 ;
906 ; Use: Scans through icons, returning their coordinates in the
907 ; block.
908 ;
909 ; This routine is exported, although it isn't for user
910 ; consumption. People using it in application code will be
911 ; shot.
912
913 EXPORT vw__enum
914 vw__enum ROUT
915
916 STMFD R13!,{R0,R2,R3,R5-R8,R14} ;Save some registers
917
918 ; --- Set up for first go round ---
919
920 CMP R1,#0 ;Is this the first go?
921 BNE %05vw__enum ;No -- skip onwards then
922
923 MOV R4,#0 ;Yes -- start at top left
924
925 ADD R14,R10,#vw__iconWidth ;Find the icon dimensions
926 LDMIA R14,{R7,R14} ;Load them out of the block
927 MOV R5,#vw__iconGap ;Set up the gap nicely
928 ADD R7,R5,R7 ;Work out right hand side
929 MOV R8,#-vw__iconGap ;Work out top edge
930 SUB R6,R8,R14 ;And set up the bottom
931 STMIA R2,{R5-R8} ;Save all of those away
932 B %10vw__enum ;Now skip on to next bit
933
934 ; --- Sort out a subsequent round ---
935
936 05vw__enum LDMIA R2,{R5,R6} ;Load bottom left of icon
937 ADD R14,R10,#vw__iconWidth ;Find the icon dimensions
938 LDMIA R14,{R7,R8} ;Load them out of the block
939 ADD R4,R4,#1 ;Bump horizontal position
940 LDR R14,[R10,#vw__across] ;How many icons going across?
941 CMP R4,R14 ;Reached the edge yet?
942 ADDCC R5,R5,R7 ;No -- move along then
943 ADDCC R5,R5,#vw__iconGap ;Add on our extra spacing
944 MOVCS R5,#vw__iconGap ;Otherwise go back to left
945 MOVCS R4,#0 ;Return left side position
946 SUBCS R6,R6,R8 ;Drop down one row
947 SUBCS R6,R6,#vw__iconGap ;And add on the spacing
948 ADD R7,R5,R7 ;Work out other box position
949 ADD R8,R6,R8 ;To make the box right
950 STMIA R2,{R5-R8} ;Store all that away
951
952 ; --- Now advance the icon pointer ---
953
954 10vw__enum LDR R0,[R10,#vw__list] ;Load the list base
955 MOV R2,#0 ;Give me all the icons
956 MOV R3,#0 ;I really mean that
957 LDR R5,[R10,#vw__listDef] ;Find the list block
958 MOV R14,PC ;Set up return address
959 ADD PC,R5,#vw__enumerate ;Get the next item
960 LDMFD R13!,{R0,R2,R3,R5-R8,R14} ;Unstack registers
961 ORRCSS PC,R14,#C_flag ;If more to come, OK
962 BICCCS PC,R14,#C_flag ;Otherwise return the end
963
964 LTORG
965
966 ; --- vw__withinBox ---
967 ;
968 ; On entry: R1 == 0 for first call, or pointer from previous
969 ; R2 == pointer to 16-byte buffer
970 ; R3 == pointer to coordinate box (window relative)
971 ; R4 == value from previous call
972 ; R10 == pointer to viewer block
973 ;
974 ; On exit: CS if match found, and
975 ; R1 == item handle of match
976 ; R4 == continuation value
977 ; else CC and
978 ; R1,R4 corrupted
979 ;
980 ; Use: Enumerates icons which intersect a given rectangle. The
981 ; coordinates of a matching icon are left in the block; these
982 ; must be set up correctly for the next call.
983
984 vw__withinBox ROUT
985
986 STMFD R13!,{R0,R14} ;Save some registers
987 MOV R0,#vwShape_intersects ;Get shape fn reason code
988 00 BL vw__enum ;Get another icon
989 BCC %10vw__withinBox ;If no more, return now
990 BL vw__intSimple ;Check simple intersection
991 BLCS vw__callShape ;And then the complex one
992 BCC %b00 ;If no match, skip back
993 LDMFD R13!,{R0,R14} ;Restore registers
994 ORRS PC,R14,#C_flag ;And return match
995
996 10vw__withinBox LDMFD R13!,{R0,R14} ;Restore registers
997 BICS PC,R14,#C_flag ;Return no match
998
999 LTORG
1000
1001 ; --- vw__iconBox ---
1002 ;
1003 ; On entry: R1 == item pointer
1004 ; R2 == pointer to a block to fill in
1005 ; R10 == viewer handle
1006 ;
1007 ; On exit: --
1008 ;
1009 ; Use: Works out the bounding box of an icon (within the window).
1010
1011 vw__iconBox ROUT
1012
1013 STMFD R13!,{R0-R5,R14} ;Save some registers
1014
1015 ; --- First, get the icon index ---
1016
1017 LDR R0,[R10,#vw__list] ;Load the list head pointer
1018 LDR R5,[R10,#vw__listDef] ;Find the definition too
1019 MOV R14,PC ;Set up return address
1020 ADD PC,R5,#vw__itemToIndex ;Find the item's index
1021
1022 ; --- Now work out its across and down position ---
1023
1024 MOV R0,R1 ;Get the item index
1025 LDR R1,[R10,#vw__across] ;Find icons going across
1026 BL divide ;Do the division
1027
1028 ; --- Finally find the actual position ---
1029
1030 ADD R14,R10,#vw__iconWidth ;Point to icon dimens
1031 LDMIA R14,{R4,R5} ;Load the width and height
1032 ADD R3,R4,#vw__iconGap ;Add on the gap here
1033 ADD R14,R5,#vw__iconGap ;And again, please
1034 MUL R14,R0,R14 ;Work out vertical placing
1035 MUL R0,R1,R3 ;And the horizontal placing
1036 RSB R14,R14,#0 ;Make vertical position -ve
1037 ADD R0,R0,#vw__iconGap ;Push the icon in a little
1038 SUB R14,R14,#vw__iconGap ;And push it down a little
1039 ADD R3,R0,R4 ;Work out the right side
1040 SUB R1,R14,R5 ;And the bottom edge
1041 STMIA R2,{R0,R1,R3,R14} ;Save them in my block
1042 LDMFD R13!,{R0-R5,PC}^ ;And return to caller
1043
1044 LTORG
1045
1046 ;----- Default selection model ----------------------------------------------
1047
1048 ; --- viewer_select ---
1049 ;
1050 ; On entry: R0 == viewer handle
1051 ; R1 == icon handle
1052 ; R2 == 0 to unselect, 1 to select or 2 to toggle
1053 ;
1054 ; On exit: --
1055 ;
1056 ; Use: Selects an icon, or maybe unselects it. Whatever, it doesn't
1057 ; flicker if it doesn't need to.
1058
1059 EXPORT viewer_select
1060 viewer_select ROUT
1061
1062 CMP R1,#0 ;Is there an icon?
1063 MOVEQS PC,R14 ;No -- do nothing then
1064
1065 STMFD R13!,{R0-R5,R10,R14} ;Save some registers
1066 MOV R10,R0 ;Get the viewer block pointer
1067
1068 ; --- Read the current flags ---
1069
1070 LDR R4,[R10,#vw__listDef] ;Get the list definition
1071 MOV R5,R2 ;And get the argument
1072 MOV R3,#0 ;Don't toggle flags
1073 MOV R2,#0 ;Don't clear any flags
1074 LDR R0,[R10,#vw__list] ;Load the list base address
1075 MOV R14,PC ;Set up return address
1076 ADD PC,R4,#vw__setFlags ;Read the current flags
1077
1078 ; --- Work out the new ones ---
1079
1080 AND R2,R2,#1 ;Leave only selected flag
1081 CMP R5,#1 ;What is the operation?
1082 MOVLT R3,#0 ;Clear -- clear the flag
1083 MOVEQ R3,#1 ;Set -- set the flag
1084 EORGT R3,R2,#1 ;Toggle -- toggle the flag
1085 CMP R3,R2 ;Have we made a difference?
1086 LDMEQFD R13!,{R0-R5,R10,PC}^ ;No -- return now then
1087
1088 ; --- Set the new flags now ---
1089
1090 MOV R2,#1 ;Clear the selected bit
1091 MOV R14,PC ;Set up return address
1092 ADD PC,R4,#vw__setFlags ;Set the new flags
1093 MOV R0,R10 ;Get handle in R0
1094 BL viewer_update ;Update the icon
1095 LDMFD R13!,{R0-R5,R10,PC}^ ;Return to caller
1096
1097 LTORG
1098
1099 ; --- viewer_isSelected ---
1100 ;
1101 ; On entry: R0 == viewer handle
1102 ; R1 == icon handle
1103 ;
1104 ; On exit: CS if icon is selected, else CC
1105 ;
1106 ; Use: Informs you whether an icon is selected.
1107
1108 EXPORT viewer_isSelected
1109 viewer_isSelected ROUT
1110
1111 CMP R1,#0 ;Is there an icon?
1112 BICEQS PC,R14,#C_flag ;No -- not selected then
1113 STMFD R13!,{R0-R4,R14} ;Save some registers
1114 MOV R2,#0 ;Don't clear any flags
1115 MOV R3,#0 ;Don't toggle any either
1116 LDR R4,[R0,#vw__listDef] ;Find the list block
1117 LDR R0,[R0,#vw__list] ;Find the list base
1118 MOV R14,PC ;Set up return address
1119 ADD PC,R4,#vw__setFlags ;Read the current flags
1120 TST R2,#1 ;Is it selected then?
1121 LDMFD R13!,{R0-R4,R14} ;Restore caller's registers
1122 ORRNES PC,R14,#C_flag ;If selected, return C set
1123 BICEQS PC,R14,#C_flag ;Otherwise clear C on exit
1124
1125 LTORG
1126
1127 ; --- viewer_selectAll ---
1128 ;
1129 ; On entry: R0 == viewer handle
1130 ; R2 == 0 to deselect, or 1 to select
1131 ;
1132 ; On exit: --
1133 ;
1134 ; Use: Selects or deselects all the icons in a viewer.
1135
1136 EXPORT viewer_selectAll
1137 viewer_selectAll ROUT
1138
1139 STMFD R13!,{R0-R5,R10,R14} ;Save some registers
1140 MOV R10,R0 ;Look after the handle
1141 MOV R1,#0 ;Start at the beginning
1142 MOV R4,R2 ;Look after selection state
1143 LDR R5,[R10,#vw__listDef] ;Find the list block
1144
1145 00 LDR R0,[R10,#vw__list] ;Find the list head
1146 MOV R2,#1 ;Check the selected bit
1147 EOR R3,R4,#1 ;Find interesting icons
1148 MOV R14,PC ;Set up return address
1149 ADD PC,R5,#vw__enumerate ;Find next icon
1150 BCC %f00 ;If all done, skip on
1151 MOV R0,R10 ;Get viewer handle
1152 MOV R2,R4 ;Get selection state
1153 BL viewer_select ;Do the selection
1154 B %b00 ;And skip back for the rest
1155
1156 00 MOV R14,#0 ;Clear temporary selection
1157 STR R14,[R10,#vw__tempSel] ;Store that in the block
1158 LDMFD R13!,{R0-R5,R10,PC}^ ;Return to caller when done
1159
1160 LTORG
1161
1162 ; --- viewer_click ---
1163 ;
1164 ; On entry: R0 == viewer handle
1165 ; R1 == icon handle (or 0)
1166 ; R2 == mouse button state
1167 ;
1168 ; On exit: --
1169 ;
1170 ; Use: Handles a click, drag etc. according to the standard
1171 ; selection model.
1172
1173 EXPORT viewer_click
1174 viewer_click ROUT
1175
1176 TST R2,#&002 ;Is this a menu click?
1177 BNE %20viewer_click ;Yes -- handle it then
1178 TST R2,#&400 ;Is this a SELECT click?
1179 BNE %10viewer_click ;Yes -- handle that
1180 TST R2,#&050 ;Is this a drag?
1181 BNE %50viewer_click ;Yes -- start a drag box
1182 TST R2,#&100 ;Is this an ADJUST click?
1183 MOVEQS PC,R14 ;No -- do nothing then
1184
1185 ; --- Handle an ADJUST click ---
1186
1187 STMFD R13!,{R2,R14} ;Save some registers
1188 BL viewer_clearTemp ;Clear temporary selection
1189 MOV R2,#2 ;Now select interesting icon
1190 BL viewer_select ;Do the selection op
1191 LDMFD R13!,{R2,PC}^ ;And return to caller
1192
1193 ; --- Handle a SELECT click ---
1194
1195 10viewer_click STMFD R13!,{R2,R14} ;Save some registers
1196 BL viewer_clearTemp ;Clear temporary selection
1197 BL viewer_isSelected ;Is the icon selected?
1198 LDMCSFD R13!,{R2,PC}^ ;Yes -- do nothing then
1199 MOV R2,#0 ;Clear entire selection
1200 BL viewer_selectAll ;Do that then
1201 MOV R2,#1 ;Now select my icon
1202 BL viewer_select ;Go do that then
1203 LDMFD R13!,{R2,PC}^ ;And return to caller
1204
1205 ; --- Handle a MENU click ---
1206
1207 20viewer_click STMFD R13!,{R0-R5,R10,R14} ;Save some registers
1208 MOV R10,R0 ;Look after the handle
1209 BL viewer_clearTemp ;Clear temporary selection
1210 MOV R4,R1 ;Look after icon handle
1211 LDR R5,[R10,#vw__listDef] ;Find the list definition
1212 LDR R0,[R10,#vw__list] ;Find the list base
1213 MOV R1,#0 ;Start at the beginning
1214 MOV R2,#1 ;Check selected bit
1215 MOV R3,#1 ;Any with it set?
1216 MOV R14,PC ;Set return address
1217 ADD PC,R5,#vw__enumerate ;Find first selected icon
1218 LDMCSFD R13!,{R0-R5,R10,PC}^ ;Robust selection -- quit now
1219 MOV R0,R10 ;Get the handle back
1220 MOV R1,R4 ;Get clicked icon
1221 MOV R2,#1 ;Select the icon
1222 BL viewer_select ;Go select it then
1223 STR R1,[R10,#vw__tempSel] ;This is temporary selection
1224 LDMFD R13!,{R0-R5,R10,PC}^ ;Return to caller
1225
1226 ; --- Handle a drag ---
1227
1228 50viewer_click CMP R1,#0 ;Is there actually an icon?
1229 BNE %60viewer_click ;Yes -- handle that
1230 STMFD R13!,{R0-R5,R14} ;Save some registers
1231 MOV R4,R0 ;Pass viewer handle in R10
1232 MOV R5,#0 ;I have no workspace
1233 LDR R0,[R4,#vw__window] ;Load the window handle
1234 MOV R1,#0 ;No flags to set
1235 ADR R2,vw__dragSel ;Point to drag handler
1236 MOV R3,#0 ;No magic number in R9
1237 BL drag_start ;Start the drag operation
1238 LDMFD R13!,{R0-R5,PC}^ ;And return to caller
1239
1240 ; --- Handle drag on an icon -- select it ---
1241
1242 60viewer_click STMFD R13!,{R2,R14} ;Save some registers
1243 MOV R2,#1 ;Select the icon
1244 BL viewer_select ;Do that then
1245 LDMFD R13!,{R2,PC}^ ;And return to caller
1246
1247 LTORG
1248
1249 ; --- vw__dragSel ---
1250 ;
1251 ; On entry: R0 == drag op event code
1252 ; Other registers depend on this
1253 ;
1254 ; On exit: --
1255 ;
1256 ; Use: Handles events during a marquee-select drag operation.
1257
1258 vw__dragSel ROUT
1259
1260 CMP R0,#7 ;Is this a kosher event?
1261 ADDCC PC,PC,R0,LSL #2 ;Yes -- then dispatch it
1262 MOVS PC,R14 ;Otherwise ignore it
1263
1264 B vw__dragRender ;Draw the drag box
1265 B vw__dragRender ;Undraw the drag box
1266 B vw__dragRender ;Rotate the drag box
1267 MOVS PC,R14 ;Do no coordinate conversion
1268 B vw__dragScroll ;Auto-scroll the viewer
1269 B vw__dragDone ;Completed the drag OK
1270 MOVS PC,R14 ;Drag operation cancelled
1271
1272 ; --- Draw the drag box ---
1273
1274 vw__dragRender STMFD R13!,{R0-R5,R14} ;Save some registers
1275
1276 ; --- Set the colour up ---
1277
1278 MOV R0,#1 ;Background colour is 1
1279 MOV R1,#7 ;Make lines black, please
1280 BL drag_eorColour ;Set the colour up
1281
1282 ; --- Now render the drag box ---
1283
1284 SUB R4,R4,R2 ;Get the box width
1285 SUB R5,R5,R3 ;And the box height
1286
1287 MOV R0,#4 ;Move cursor absolute
1288 ADD R1,R6,R2 ;Find the start position
1289 ADD R2,R7,R3 ;Set up the y position too
1290 SWI OS_Plot ;Move the graphics cursor
1291
1292 MOV R0,#17 ;Relative dotted plot
1293 MOV R1,R4 ;Plot bottom line
1294 MOV R2,#0 ;Keep y constant
1295 SWI OS_Plot
1296 MOV R0,#49 ;Relative dotted plot
1297 MOV R1,#0 ;Keep x constant
1298 MOV R2,R5 ;Plot right hand side
1299 SWI OS_Plot
1300 MOV R0,#49 ;Relative dotted plot
1301 RSB R1,R4,#0 ;Plot top line
1302 MOV R2,#0 ;Keep y constant
1303 SWI OS_Plot
1304 MOV R0,#57 ;Relative dotted plot
1305 MOV R1,#0 ;Keep x constant
1306 RSB R2,R5,#0 ;Plot left hand side
1307 SWI OS_Plot ;Plot that too
1308
1309 LDMFD R13!,{R0-R5,PC}^ ;And return to caller
1310
1311 ; --- Scroll the window during the drag ---
1312
1313 vw__dragScroll STMFD R13!,{R0-R3,R14} ;Save some registers
1314 BL drag_scroll ;Get the scroll position
1315 STR R3,[R1,#24] ;Save vertical scroll posn
1316 BL vw__openWindow ;Reopen the window
1317 LDMFD R13!,{R0-R3,PC}^ ;And return to caller
1318
1319 ; --- Handle the end of the drag ---
1320
1321 vw__dragDone STMFD R13!,{R0-R5,R14} ;Save some registers
1322
1323 ; --- Fiddle the coordinates ---
1324
1325 CMP R2,R4 ;Are these the right way?
1326 EORGT R2,R2,R4 ;No -- swap them round then
1327 EORGT R4,R2,R4
1328 EORGT R2,R2,R4
1329
1330 CMP R3,R5 ;Are these the right way?
1331 EORGT R3,R3,R5 ;No -- swap them round then
1332 EORGT R5,R3,R5
1333 EORGT R3,R3,R5
1334
1335 ; --- Now enumerate matching boxes ---
1336
1337 STMFD R13!,{R2-R5} ;Stuff the drag box on stack
1338 SUB R13,R13,#16 ;And make another block
1339
1340 MOV R0,R10 ;Get the viewer handle
1341 MOV R1,#0 ;Start at the beginning
1342 ADD R3,R13,#16 ;Point at the drag box
1343
1344 00 MOV R2,R13 ;Point to my spare block
1345 BL vw__withinBox ;Get next matching icon
1346 MOVCS R2,#1 ;Select this icon please
1347 BLCS viewer_select ;Please do that
1348 BCS %b00 ;And loop back
1349
1350 ; --- Finished -- return ---
1351
1352 ADD R13,R13,#32 ;Restore the stack block
1353 LDMFD R13!,{R0-R5,PC}^ ;And return to caller
1354
1355 LTORG
1356
1357 ; --- viewer_clearTemp ---
1358 ;
1359 ; On entry: R0 == viewer handle
1360 ;
1361 ; On exit: --
1362 ;
1363 ; Use: Clears the temporary selection (use when you receive a
1364 ; menu closed event).
1365
1366 viewer_clearTemp ROUT
1367
1368 STMFD R13!,{R1,R2,R14} ;Save some registers
1369 LDR R1,[R0,#vw__tempSel] ;Find temporary selection
1370 CMP R1,#0 ;Is that defined?
1371 LDMEQFD R13!,{R1,R2,PC}^ ;No -- return now
1372 MOV R2,#0 ;Yes -- deselect the icon
1373 BL viewer_select ;Go do that then
1374 MOV R14,#0 ;And also clear temp select
1375 STR R14,[R0,#vw__tempSel] ;Store that in the block
1376 LDMFD R13!,{R1,R2,PC}^ ;Return to caller when done
1377
1378 LTORG
1379
1380 ; --- viewer_dragSelection ---
1381 ;
1382 ; On entry: R0 == viewer handle
1383 ;
1384 ; On exit: --
1385 ;
1386 ; Use: Starts a drag of the icons within the viewer. When the drag
1387 ; is finished, you get sent a vwEvent_dragged event.
1388
1389 EXPORT viewer_dragSelection
1390 viewer_dragSelection ROUT
1391
1392 STMFD R13!,{R0-R10,R14} ;Save lots of registers
1393 MOV R10,R0 ;Look after the viewer handle
1394 LDR R9,[R10,#vw__listDef] ;Find the list definition
1395
1396 ; --- First, see if we need DragASprite ---
1397
1398 MOV R0,#161 ;Read CMOS locations
1399 MOV R1,#28 ;Various strange status flags
1400 SWI OS_Byte ;Do the read op
1401 TST R2,#2 ;Is the bit set?
1402 BEQ %50viewer_dragSelection ;No -- use normal Wimp box
1403
1404 ; --- Work out what sprite to use ---
1405 ;
1406 ; We need to ask the client here.
1407
1408 LDR R0,[R10,#vw__list] ;Load the list base pointer
1409 MOV R1,#0 ;Start at the beginning
1410 MOV R2,#1 ;Check the selected bit
1411 MOV R3,#1 ;Make sure it's on
1412 MOV R14,PC ;Set up return address
1413 ADD PC,R9,#vw__enumerate ;Read first matching item
1414 BCC %90viewer_dragSelection ;No selection -- no drag
1415 MOVCS R4,R1 ;Match -- get icon handle
1416 MOVCS R14,PC ;And set up again
1417 ADDCS PC,R9,#vw__enumerate ;Read next matching iten
1418 MOVCS R4,#-1 ;If more than one, say `many'
1419
1420 MOV R1,R4 ;Give this to the client
1421 MOV R0,#vwEvent_sprite ;Pretend it's an event
1422 BL vw__dispatch ;And send it off nicely
1423 BCC %50viewer_dragSelection ;Told to use Wimp box
1424
1425 ; --- Now use DragASprite nicely ---
1426
1427 MOV R2,R1 ;Look after the name
1428 MOV R3,R0 ;And the sprite area
1429 SUB R13,R13,#20 ;Make a small block
1430 MOV R1,R13 ;Point to the block
1431 SWI Wimp_GetPointerInfo ;Read the pointer position
1432 MOV R14,R13 ;Point to the block
1433 LDMIA R14,{R0,R1} ;Load the coordinates out
1434 SUB R0,R0,#64 ;Turn into a little box
1435 SUB R1,R1,#64 ;Chop off a little bit
1436 STMIA R14!,{R0,R1} ;Store them back
1437 ADD R0,R0,#128 ;Work out the other side
1438 ADD R1,R1,#128 ;Add on quite a lot actually
1439 STMIA R14!,{R0,R1} ;Store them back
1440
1441 MOV R0,#&C5 ;DragASprite flags
1442 MOV R1,R3 ;Get the sprite area
1443 MOV R3,R13 ;Point to my rectangle block
1444 SWI XDragASprite_Start ;Start the drag operation
1445 ADD R13,R13,#20 ;Reclaim the stack pointer
1446 BVC %70viewer_dragSelection ;If it worked, set up handler
1447
1448 ; --- Try and do a dotted outline ---
1449
1450 50 SUB R13,R13,#40 ;Make a small block
1451 LDR R0,[R10,#vw__list] ;Find the list definition
1452 MOV R1,#0 ;Start at the beginning
1453 MOV R2,#1 ;Check selected bits
1454 MOV R3,#1 ;Make sure they're on
1455 MOV R14,PC ;Set up return address
1456 ADD PC,R9,#vw__enumerate ;Do the enumeration
1457 ADDCC R13,R13,#40 ;Restore stack pointer
1458 BCC %90viewer_dragSelection ;No selection -- no drag
1459
1460 MOV R2,R13 ;Point to a block
1461 BL vw__iconBox ;Find the icon's bounding box
1462 LDMIA R2,{R4-R7} ;Load the bounding box
1463
1464 ; --- Now work out the bounding box of selected icons ---
1465
1466 00 MOV R2,#1 ;Check selected bits
1467 MOV R3,#1 ;Make sure they're on
1468 MOV R14,PC ;Set up return address
1469 ADD PC,R9,#vw__enumerate ;Do the enumeration
1470 BCC %f00 ;No more -- skip onwards
1471 MOV R2,R13 ;Point to a block
1472 BL vw__iconBox ;Find the bounding box
1473 LDMIA R2,{R2,R3,R8,R14} ;Load these coordinates
1474
1475 CMP R4,R2
1476 MOVGT R4,R2
1477 CMP R5,R3
1478 MOVGT R5,R3
1479 CMP R6,R8
1480 MOVLT R6,R8
1481 CMP R7,R14
1482 MOVLT R7,R14
1483
1484 B %b00 ;Loop back for the rest now
1485
1486 ; --- Translate coordinates to screen relative ---
1487
1488 00 MOV R1,R13 ;Point to my block
1489 SWI Wimp_GetPointerInfo ;Read the pointer position
1490 LDMIA R13,{R8,R9} ;Load the position out
1491
1492 LDR R14,[R10,#vw__window] ;Load the window handle
1493 STR R14,[R13,#0] ;Store it in the block
1494 SWI Wimp_GetWindowState ;Read the window position
1495 LDR R0,[R13,#4] ;Load the left hand side
1496 ADD R14,R13,#16 ;Point to top edge/scroll
1497 LDMIA R14,{R1-R3} ;Load those out nicely
1498 SUB R2,R0,R2 ;Work out x origin pos
1499 SUB R3,R1,R3 ;And the y origin pos
1500
1501 ADD R4,R4,R2
1502 ADD R5,R5,R3
1503 ADD R6,R6,R2
1504 ADD R7,R7,R3
1505
1506 SUB R4,R4,#vw__iconGap /2
1507 SUB R5,R5,#vw__iconGap /2
1508 ADD R6,R6,#vw__iconGap /2
1509 ADD R7,R7,#vw__iconGap /2
1510
1511 ADD R14,R13,#8 ;Point to bit of block
1512 STMIA R14,{R4-R7} ;Save the drag box position
1513
1514 ; --- Work out the parent box position ---
1515
1516 SUB R4,R4,R8 ;Work out min x position
1517 SUB R5,R5,R9 ;And the min y position
1518 SUB R6,R6,R8 ;Fiddle with max x
1519 SUB R7,R7,R9 ;And max y
1520 BL screen_getInfo ;Read the screen information
1521 ADD R14,R0,#screen_width ;Find the screen dimensions
1522 LDMIA R14,{R8,R9} ;Load them out nicely
1523 ADD R6,R6,R8 ;Work out max x position
1524 ADD R7,R7,R9 ;And the max y position
1525 ADD R14,R0,#screen_dx ;Get the pixel sizes
1526 LDMIA R14,{R8,R9} ;Load those out too
1527 SUB R6,R6,R8 ;Subtract a pixel off
1528 SUB R7,R7,R9 ;To make things nice
1529 ADD R14,R13,#24 ;Point to parent box area
1530 STMIA R14,{R4-R7} ;Save that lot away
1531
1532 ; --- Start the drag (phew...) ---
1533
1534 MOV R14,#5 ;Drag fixed sized box
1535 STR R14,[R13,#4] ;Store it in the block
1536 MOV R1,R13 ;Point to the block
1537 SWI Wimp_DragBox ;And start the drag op
1538 ADD R13,R13,#40 ;Reclaim my drag box block
1539
1540 ; --- Set up my handler at the end of it ---
1541
1542 70 ADR R0,vw__dragIcn ;Point to my handler
1543 MOV R2,R10 ;Pass viewer handle in R10
1544 MOV R3,R12 ;And workspace (?) in R12
1545 BL win_unknownHandler ;Register that routine please
1546 90 LDMFD R13!,{R0-R10,PC}^ ;And return to caller
1547
1548 LTORG
1549
1550 ; --- vw__dragIcn ---
1551 ;
1552 ; On entry: R0 == event code
1553 ; R1 == pointer to event block
1554 ;
1555 ; On exit: --
1556 ;
1557 ; Use: Handles events during a selection drag.
1558
1559 vw__dragIcn ROUT
1560
1561 CMP R0,#7 ;Is it a drag end event?
1562 MOVNES PC,R14 ;Nope -- nothing to do
1563
1564 STMFD R13!,{R0-R2,R14} ;Save some registers
1565 SWI XDragASprite_Stop ;Turn off any sprite drags
1566 SUB R13,R13,#20 ;Make a little block
1567 MOV R1,R13 ;Point to the block
1568 SWI Wimp_GetPointerInfo ;Read the pointer position
1569 ADD R14,R1,#12 ;Point to window handle
1570 LDMIA R14,{R1,R2} ;Load window and icon
1571 ADD R13,R13,#20 ;Restore stack block
1572 MOV R0,#vwEvent_dragged ;Get the event code
1573 BL vw__dispatch ;Send it the event
1574 LDMFD R13!,{R0-R2,PC}^ ;And return to caller
1575
1576 LTORG
1577
1578 ;----- Miscellaneous --------------------------------------------------------
1579
1580 ; --- viewer_window ---
1581 ;
1582 ; On entry: R0 == viewer handle
1583 ;
1584 ; On exit: R0 == window handle
1585 ;
1586 ; Use: Returns the window handle of the viewer.
1587
1588 EXPORT viewer_window
1589 viewer_window ROUT
1590
1591 LDR R0,[R0,#vw__window] ;Load the window handle
1592 MOVS PC,R14 ;And return to caller
1593
1594 LTORG
1595
1596 ; --- viewer_update ---
1597 ;
1598 ; On entry: R0 == viewer handle
1599 ; R1 == icon handle
1600 ;
1601 ; On exit: --
1602 ;
1603 ; Use: Updates (redraws) a given icon.
1604
1605 EXPORT viewer_update
1606 viewer_update ROUT
1607
1608 STMFD R13!,{R2,R14} ;Save some registers
1609 MOV R2,#vwEvent_redraw ;Normal is redraw event
1610 BL vw__doUpdate ;Go and do the update
1611 LDMFD R13!,{R2,PC}^ ;And return to caller
1612
1613 LTORG
1614
1615 ; --- vw__doUpdate ---
1616 ;
1617 ; On entry: R0 == viewer handle
1618 ; R1 == icon handle
1619 ; R2 == event code to send
1620 ;
1621 ; On exit: --
1622 ;
1623 ; Use: Updates an item, passing a given event to the client. This
1624 ; is purely for the use of gallery ;-)
1625
1626 EXPORT vw__doUpdate
1627 vw__doUpdate ROUT
1628
1629 STMFD R13!,{R0-R7,R10,R14} ;Save some registers
1630 MOV R10,R0 ;Get the viewer handle in R10
1631 MOV R7,R2 ;Find the event code
1632
1633 ; --- Start the update job ---
1634
1635 SUB R13,R13,#32+44 ;Make a rectangle block
1636 MOV R2,R13 ;Point to space for box
1637 BL vw__iconBox ;Find the icon's box
1638
1639 LDMIA R2,{R2-R5} ;Load the box coordinates
1640 ADD R14,R13,#32+4 ;Find the update block
1641 STMIA R14,{R2-R5} ;Store the rectangle there
1642 LDR R14,[R10,#vw__window] ;Load the window handle
1643 STR R14,[R13,#32+0] ;Store in my nice block
1644 MOV R4,R1 ;Look after icon handle
1645 ADD R1,R13,#32 ;Point to update block
1646 SWI Wimp_UpdateWindow ;Start the update job
1647 CMP R0,#0 ;Anything to do?
1648 BEQ %90vw__doUpdate ;No -- skip to end then
1649
1650 ; --- Read the window origin ---
1651
1652 LDR R2,[R13,#32+4] ;Load the left hand side
1653 ADD R14,R13,#32+16 ;Find top and scroll offsets
1654 LDMIA R14,{R3,R5,R6} ;Load those out too
1655 SUB R6,R3,R6 ;Find the y origin position
1656 SUB R5,R2,R5 ;And the x origin position
1657
1658 ; --- Now embark on the main loop ---
1659
1660 00 ADD R14,R13,#32+28 ;Point to graphics rectangle
1661 LDMIA R14,{R0-R3} ;Load that out
1662 SUB R0,R0,R5 ;Adjust the block by origin
1663 SUB R1,R1,R6 ;This is just to keep the
1664 SUB R2,R2,R5 ;User's event handler happy
1665 SUB R3,R3,R6 ;I know what needs to be done
1666 STMIA R14,{R0-R3} ;Store that lot back
1667
1668 MOV R0,R7 ;Get the redraw event ready
1669 MOV R1,R4 ;Point to the item
1670 MOV R2,R13 ;Point to his icon block
1671 ADD R3,R13,#32+28 ;Point to clipping block
1672 BL vw__dispatch ;Send to the handler
1673
1674 ; --- Do any other bits of drawing ---
1675
1676 ADD R1,R13,#32 ;Point to update block
1677 CMP R7,#vwEvent_draw ;Gallery redraw event? (yuk)
1678 BLEQ drag_redraw ;Yes -- update drag rectangle
1679 SWI Wimp_GetRectangle ;Do that rectangle
1680 CMP R0,#0 ;Any more to do?
1681 BNE %b00 ;Yes -- do it then
1682
1683 ; --- Wrap up and return ---
1684
1685 90 ADD R13,R13,#32+44 ;Restore the stack
1686 LDMFD R13!,{R0-R7,R10,PC}^ ;And return to caller
1687
1688 LTORG
1689
1690 ; --- viewer_setTitle ---
1691 ;
1692 ; On entry: R0 == viewer handle
1693 ; R1 == title string
1694 ;
1695 ; On exit: --
1696 ;
1697 ; Use: Sets the viewer window's title.
1698
1699 EXPORT viewer_setTitle
1700 viewer_setTitle ROUT
1701
1702 STMFD R13!,{R0-R2,R10,R14} ;Save some registers
1703 MOV R10,R0 ;Get the viewer handle
1704 LDR R2,[R10,#vw__window] ;Load the window handle
1705 MOV R0,R1 ;Get the string to set
1706 ADD R1,R10,#vw__title ;Point to title bar buffer
1707 BL winUtils_setTitle ;Do the title setting
1708 BL vw__open ;Is the window open?
1709 LDMCCFD R13!,{R0-R2,R10,PC}^ ;No -- do nothing then
1710
1711 SUB R13,R13,#36 ;Make a window state block
1712 LDR R14,[R10,#vw__window] ;Load the window handle
1713 STR R14,[R13,#0] ;Store it in the block
1714 MOV R1,R13 ;Point to the block
1715 SWI Wimp_GetWindowState ;Read the current position
1716
1717 BL vw__tWidth ;Yes -- reset the width
1718 BL vw__setExtent ;And reset the extent
1719 BL vw__openWindow ;Open the window, in case
1720 ADD R13,R13,#36 ;And reset the stack pointer
1721 LDMFD R13!,{R0-R2,R10,PC}^ ;And return to caller
1722
1723 LTORG
1724
1725 ; --- vw__open ---
1726 ;
1727 ; On entry: R10 == pointer to viewer block
1728 ;
1729 ; On exit: CS if window is open, else CC
1730 ;
1731 ; Use: Sees if a viewer window is currently open.
1732
1733 vw__open ROUT
1734
1735 STMFD R13!,{R0,R1,R14} ;Save some registers
1736 SUB R13,R13,#36 ;Make some space
1737 LDR R14,[R10,#vw__window] ;Load the window handle
1738 STR R14,[R13,#0] ;Save it in the block
1739 MOV R1,R13 ;Point to the block
1740 SWI Wimp_GetWindowState ;Read the information
1741 LDR R14,[R13,#32] ;Load the flags word
1742 TST R14,#1<<16 ;Is the window open?
1743 ADD R13,R13,#36 ;Reclaim the stack space
1744 LDMFD R13!,{R0,R1,R14} ;Restore registers
1745 ORRNES PC,R14,#C_flag ;Return with C set if so
1746 BICEQS PC,R14,#C_flag ;Otherwise clear C
1747
1748 LTORG
1749
1750 ; --- vw__openWindow ---
1751 ;
1752 ; On entry: R1 == pointer to window state block
1753 ; R10 == pointer to viewer block
1754 ;
1755 ; On exit: R0 corrupted (just like Wimp_OpenWindow)
1756 ;
1757 ; Use: Opens a viewer window, and informs the user through the
1758 ; vwEvent_open event.
1759
1760 vw__openWindow ROUT
1761
1762 SWI Wimp_OpenWindow ;Reopen the window as ordered
1763 MOV R0,#vwEvent_open ;Send the event along nicely
1764 B vw__dispatch ;And report, and return
1765
1766 LTORG
1767
1768 ; --- vw__tWidth ---
1769 ;
1770 ; On entry: R10 == pointer to viewer block
1771 ;
1772 ; On exit: --
1773 ;
1774 ; Use: Updates the window's fixed width parameter.
1775
1776 vw__tWidth ROUT
1777
1778 STMFD R13!,{R0,R1,R14} ;Save some registers
1779 ADD R0,R10,#vw__title ;Point to title buffer
1780 BL wimp_strWidth ;Get the string width
1781 ADD R1,R0,#vw__titleAdd ;Add on a fudge factor
1782 LDR R0,[R10,#vw__banner] ;Load the banner address
1783 CMP R0,#0 ;Is the banner there?
1784 BLNE wimp_strWidth ;Yes -- get its width
1785 ADDNE R0,R0,#vw__banAdd ;And add on its fudge
1786 CMP R1,R0 ;Which is bigger?
1787 MOVCC R1,R0 ;Use the biggest one
1788 STR R1,[R10,#vw__fixedWidth] ;Store the new width
1789 LDMFD R13!,{R0,R1,PC}^ ;And return to caller
1790
1791 LTORG
1792
1793 ; --- viewer_rescan ---
1794 ;
1795 ; On entry: R0 == viewer handle
1796 ;
1797 ; On exit: --
1798 ;
1799 ; Use: Rescans all the icons in the viewer and forces a redraw,
1800 ; in case icons have been added or deleted (or renamed). Note
1801 ; that the redraw is done *anyway* -- it's your responsibility
1802 ; to avoid calling this routine when you don't need to.
1803
1804 EXPORT viewer_rescan
1805 viewer_rescan ROUT
1806
1807 STMFD R13!,{R0,R1,R10,R14} ;Save some registers
1808 MOV R10,R0 ;Get the viewer handle
1809 BL vw__open ;Is the window open at all?
1810 LDMCCFD R13!,{R0,R1,R10,PC}^ ;No -- handle on open then
1811
1812 SUB R13,R13,#36 ;Make a window state block
1813 LDR R14,[R10,#vw__window] ;Load the window handle
1814 STR R14,[R13,#0] ;Save it in the block
1815 MOV R1,R13 ;Point to the block
1816 SWI Wimp_GetWindowState ;And read the window state
1817
1818 ; --- Open the window onto the screen ---
1819
1820 LDR R1,[R10,#vw__listDef] ;Find the list definition
1821 LDR R0,[R10,#vw__list] ;And the list base
1822 MOV R14,PC ;Set up return address
1823 ADD PC,R1,#vw__items ;Find how many items
1824 STR R1,[R10,#vw__icons] ;Store this away
1825
1826 MOV R1,R13 ;Point at window state blk
1827 BL vw__rescanSize ;Rescan the item size
1828 BL vw__extend ;Yes -- make it big then
1829 BL vw__resize ;Work out new arrangement
1830 BL vw__setExtent ;Set the window's extent
1831 BL vw__refresh ;Force update of display
1832 BL vw__openWindow ;And open the window
1833 ADD R13,R13,#36 ;Reclaim my stack space
1834 LDMFD R13!,{R0,R1,R10,PC}^ ;And return to caller
1835
1836 LTORG
1837
1838 ;----- Icon rearrangement routines ------------------------------------------
1839
1840 ; --- vw__resize ---
1841 ;
1842 ; On entry: R1 == pointer to window state block
1843 ; R10 == pointer to viewer block
1844 ;
1845 ; On exit: CS if the size has changed, else CC
1846 ;
1847 ; Use: Updates the icon arrangement within a window, returning
1848 ; whether the arrangement is different now. Note that this
1849 ; doesn't redraw the window; it just recaches the extent.
1850 ; If the size has changed, you'll probably need to call
1851 ; vw__setExtent and vw__refresh to get everything looking nice.
1852
1853 vw__resize ROUT
1854
1855 STMFD R13!,{R0-R3,R14} ;Save some registers
1856
1857 ; --- Now work out how many icons we should have ---
1858
1859 LDMIB R1,{R1-R3} ;Load the x coords from win
1860 SUB R0,R3,R1 ;Work out the window width
1861 SUB R0,R0,#vw__iconGap ;Subtract off extra border
1862 LDR R2,[R10,#vw__iconWidth] ;Load the icon width out
1863 ADD R1,R2,#vw__iconGap ;Add on the gap
1864 BL divide ;Divide one by the other
1865 MOV R3,R0 ;Icons which fit across win
1866
1867 BL screen_getInfo ;Find the screen information
1868 LDR R0,[R0,#screen_width] ;Load the screen width
1869 SUB R0,R0,#40+vw__iconGap ;Fudge for scroll bar
1870 ADD R1,R2,#vw__iconGap ;Get icon width+gap again
1871 BL divide ;Divide one by the other
1872 MOV R2,R0 ;Icons which fit across scrn
1873
1874 ; --- Fiddle these numbers appropriately ---
1875
1876 LDR R0,[R10,#vw__icons] ;Load number of icons
1877 CMP R3,R0 ;Too many across window?
1878 MOVCS R3,R0 ;Yes -- use number we have
1879 CMP R2,R0 ;Too many across screen?
1880 MOVCS R2,R0 ;Yes -- use number we have
1881 CMP R2,R3 ;More than fit across screen?
1882 MOVCS R2,R3 ;Use -- use that then (erk)
1883 CMP R2,#0 ;No icons at all?
1884 MOVEQ R2,#1 ;Then have at least one
1885
1886 ; --- Work out how many go down ---
1887
1888 MOV R1,R2 ;Get number going across
1889 BL divide ;Do the division
1890 CMP R1,#0 ;Any extra ones on bottom?
1891 ADDNE R0,R0,#1 ;Yes -- add an extra row
1892 MOVS R3,R0 ;Look after this value
1893 MOVEQ R3,#0 ;If it's zero, use one
1894
1895 ; --- Now see if anything's changed ---
1896
1897 ADD R14,R10,#vw__across ;Find old across counter
1898 LDMIA R14,{R0,R1} ;Load across and down values
1899 CMP R0,R2 ;Compare with old ones
1900 CMPEQ R1,R3 ;Are they the same?
1901 STMNEIA R14,{R2,R3} ;If not, store new ones
1902 LDMFD R13!,{R0-R3,R14} ;Restore caller's registers
1903 ORRNES PC,R14,#C_flag ;If changed, return C set
1904 BICEQS PC,R14,#C_flag ;Otherwise return C clear
1905
1906 LTORG
1907
1908 ; --- vw__setExtent ---
1909 ;
1910 ; On entry: R10 == pointer to viewer block
1911 ;
1912 ; On exit: --
1913 ;
1914 ; Use: Resets the extent of a viewer window, in case the
1915 ; arrangement of icons or banner/title text has changed.
1916 ; If the window is currently open, you should follow this
1917 ; call with a Wimp_OpenWindow SWI.
1918
1919 vw__setExtent ROUT
1920
1921 STMFD R13!,{R0-R3,R14} ;Save some registers
1922
1923 ; --- Work out correct horizontal extent ---
1924
1925 BL screen_getInfo ;Find the screen information
1926 LDR R0,[R0,#screen_width] ;Load the screen width
1927 SUB R0,R0,#40+vw__iconGap ;Fudge for scroll bar
1928 MOV R2,R0 ;Look after this value
1929 LDR R3,[R10,#vw__iconWidth] ;Load the icon width
1930 ADD R3,R3,#vw__iconGap ;Add on the inter-icon gap
1931 MOV R1,R3 ;Divide by this
1932 BL divide ;Divide one by the other
1933 LDR R14,[R10,#vw__icons] ;Load the number of icons
1934 CMP R0,R14 ;Is this bigger?
1935 MOVCS R0,R14 ;Yes -- then use that
1936 CMP R0,#0 ;Unless there's none
1937 MOVEQ R0,#1 ;In which case use one
1938 MUL R2,R3,R0 ;Work out the correct width
1939 ADD R2,R2,#vw__iconGap ;Add on extra border around
1940 LDR R14,[R10,#vw__fixedWidth] ;Load width of title/banner
1941 CMP R2,R14 ;Do we have enough here?
1942 MOVCC R2,R14 ;No -- then use more
1943
1944 ; --- And now the vertical extent ---
1945
1946 LDR R1,[R10,#vw__iconHeight] ;Load the icon height
1947 ADD R1,R1,#vw__iconGap ;Add on the gap
1948 LDR R14,[R10,#vw__down] ;Load vertical number of icns
1949 MUL R1,R14,R1 ;Work out the size
1950 ADD R1,R1,#vw__iconGap ;Add on extra border
1951
1952 ; --- Work out the other two ---
1953
1954 RSB R1,R1,#0 ;And vertical extent -ve
1955 LDR R3,[R10,#vw__banner] ;Load banner pointer
1956 CMP R3,#0 ;Do we have a banner?
1957 MOVNE R3,#vw__banHeight ;Yes -- then add above origin
1958 MOV R0,#0 ;Start at the left side
1959
1960 ; --- Make sure the extent is big enough ---
1961
1962 SUBS R14,R2,#vw__minWidth ;Get the minimum width
1963 SUBCC R2,R2,R14 ;Make bigger if needs be
1964 SUB R14,R3,R1 ;Work out extent height
1965 SUBS R14,R14,#vw__minHeight ;Get the minimum height
1966 ADDCC R1,R1,R14 ;Make bigger if needs be
1967
1968 ; --- Finally set up the extent ---
1969
1970 ADD R14,R10,#vw__extent ;Set the window extent
1971 STMIA R14,{R0-R3} ;Save the values in there
1972 LDR R0,[R10,#vw__window] ;Load the window handle
1973 ADD R1,R10,#vw__extent ;Point to the extent block
1974 SWI Wimp_SetExtent ;Set the window's extent
1975 LDMFD R13!,{R0-R3,PC}^ ;And return to caller
1976
1977 LTORG
1978
1979 ; --- vw__refresh ---
1980 ;
1981 ; On entry: R10 == pointer to a viewer block
1982 ;
1983 ; On exit: --
1984 ;
1985 ; Use: Forces a redraw of the contents of a viewer. Use in
1986 ; conjunction with vw__resize.
1987
1988 vw__refresh ROUT
1989
1990 STMFD R13!,{R0-R4,R14} ;Save some registers
1991 LDR R0,[R10,#vw__window] ;Load the window handle
1992 MOV R1,#-&FFFFFFF ;Force a redraw of the world
1993 MOV R2,#-&FFFFFFF ;This hack prevents problems
1994 MOV R3,#&FFFFFFF ;with the extent being bodged
1995 MOV R4,#&FFFFFFF ;by the Wimp.
1996 SWI Wimp_ForceRedraw ;Redraw the whole lot
1997 LDMFD R13!,{R0-R4,PC}^ ;And return to caller
1998
1999 LTORG
2000
2001 ; --- vw__extend ---
2002 ;
2003 ; On entry: R1 == pointer to window open block
2004 ; R10 == pointer to a viewer block
2005 ;
2006 ; On exit: --
2007 ;
2008 ; Use: Extends the viewer window if necessary to accomodate new
2009 ; items. The new coordinates to open are written back to the
2010 ; window open block. Correct procedure for adding items is
2011 ; as follows:
2012 ;
2013 ; 1. Get window state
2014 ; 2. Call vw__extend
2015 ; 3. Call vw__resize
2016 ; 4. Call vw__setExtent
2017 ; 5. Call vw__refresh
2018
2019 vw__extend ROUT
2020
2021 STMFD R13!,{R0-R8,R14} ;Save some registers
2022
2023 ; --- Load current and maximum width and height ---
2024
2025 MOV R8,R1 ;Look after this address
2026 LDMIB R8,{R4-R7} ;Load the window dimensions
2027 SUB R6,R6,R4 ;Find the window width
2028 SUB R7,R7,R5 ;And its height
2029
2030 ADD R14,R10,#vw__extent ;Find the current extent
2031 LDMIA R14,{R0-R3} ;Load the dimensions out
2032 SUB R4,R2,R0 ;Find the maximum width
2033 SUB R5,R3,R1 ;And the maximum height
2034 LDR R14,[R10,#vw__flags] ;Load the flags word
2035 TST R14,#vwFlag__opened ;Has viewer ever been opened?
2036 BNE %f00 ;Yes -- skip onwards
2037
2038 ; --- Set up special values for first time ---
2039
2040 MOV R4,#0 ;No -- force width to max
2041 MOV R5,#0 ;And height forced to max
2042 LDR R6,[R10,#vw__fixedWidth] ;Set a default width though
2043 CMP R6,#vw__minWidth ;Get the minimum width
2044 MOVCC R6,#vw__minWidth ;If too small, use this
2045 MOV R7,#vw__minHeight ;Use the minimum height too
2046
2047 ; --- Find out if we have anything to do horizontally ---
2048 ;
2049 ; We only try to extend if the window is currently as wide
2050 ; as it will go.
2051
2052 00 CMP R6,R4 ;Does the width shape up?
2053 BCC %50vw__extend ;No -- skip to vertical
2054
2055 ; --- Extend the width ---
2056 ;
2057 ; We ensure that the width of the window is the smaller
2058 ; of the maximum width we allow and the width of the number
2059 ; of icons in the window.
2060
2061 MOV R0,#vw__maxWidth ;Get the maximum width
2062 LDR R3,[R10,#vw__iconWidth] ;Find the icon width
2063 ADD R3,R3,#vw__iconGap ;And add on the gap as usual
2064 MOV R1,R3 ;Divide by this
2065 BL divide ;Divide one by the other
2066 LDR R1,[R10,#vw__icons] ;Load total number of icns
2067 CMP R0,R1 ;Which one is bigger?
2068 MOVCS R0,R1 ;Use the smaller
2069 CMP R0,#0 ;Are there no icons at all?
2070 MOVEQ R0,#1 ;None -- make space for one
2071 MUL R0,R3,R0 ;Work out new improved width
2072 ADD R0,R0,#vw__iconGap ;Add on the extra border
2073 CMP R6,R0 ;Which is bigger?
2074 MOVCC R6,R0 ;Use the bigger of the two
2075
2076 ; --- Now do things vertically ---
2077 ;
2078 ; This is basically the same. We only extend if the window
2079 ; is as tall at it will go.
2080
2081 50vw__extend CMP R7,R5 ;Does the height shape up?
2082 BCC %90vw__extend ;No -- skip on then
2083
2084 ; --- Extend the height ---
2085 ;
2086 ; This is trickier, because we have to work out how many
2087 ; icons there will be vertically.
2088
2089 LDR R3,[R10,#vw__iconHeight] ;Load the icon height
2090 ADD R3,R3,#vw__iconGap ;Add on the inter-icon gap
2091 SUB R0,R6,#vw__iconGap ;Get the current width
2092 LDR R1,[R10,#vw__iconWidth] ;Find the icon width
2093 ADD R1,R1,#vw__iconGap ;And add on the gap as usual
2094 BL divide ;Find how many will fit
2095
2096 MOV R1,R0 ;We will divide by this
2097 LDR R0,[R10,#vw__icons] ;Load the number of icons
2098 BL divide ;Work out number down
2099 CMP R1,#0 ;Is there a remainder?
2100 ADDNE R0,R0,#1 ;Yes -- extra one then
2101 CMP R0,#0 ;Are there no icons?
2102 MOVEQ R0,#1 ;None -- make space for one
2103 MOV R2,R0 ;Look after this value
2104
2105 MOV R0,#vw__maxHeight ;Get the maximum height
2106 MOV R1,R3 ;And the icon height
2107 BL divide ;Do the division again
2108 CMP R0,R2 ;Which one is bigger?
2109 MOVCS R0,R2 ;Use the smaller
2110 MUL R0,R3,R0 ;Work out new improved height
2111 ADD R0,R0,#vw__iconGap ;Add on the extra border
2112 LDR R14,[R10,#vw__banner] ;Do we have a banner string?
2113 CMP R14,#0 ;Quick check for that...
2114 ADDNE R0,R0,#vw__banHeight ;Yes -- add that on too
2115 CMP R7,R0 ;Which is bigger?
2116 MOVCC R7,R0 ;Use the bigger
2117
2118 ; --- Now update the window block ---
2119
2120 90vw__extend LDMIB R8,{R0-R3} ;Load the current values
2121 ADD R2,R0,R6 ;Work out new right side
2122 SUBS R1,R3,R7 ;And the new bottom
2123 SUBLT R3,R3,R1 ;Move the top if hit bottom
2124 SUBLT R1,R1,R1 ;And move the bottom too
2125 STMIB R8,{R0-R3} ;Save that lot back again
2126 LDMFD R13!,{R0-R8,PC}^ ;And return to caller
2127
2128 LTORG
2129
2130 ;----- Viewer block structure -----------------------------------------------
2131 ;
2132 ; This is shadowed by gallery.s -- keep them in step.
2133
2134 ^ 0
2135
2136 ; --- Information about the window ---
2137
2138 vw__window # 4 ;Window handle
2139 vw__extent # 16 ;Current window extent
2140 vw__flags # 4 ;Any flags of interest
2141 vw__list # 4 ;Pointer to list head
2142 vw__listDef # 4 ;Pointer to list handler
2143 vw__handler # 12 ;Viewer's event handler
2144 gl__handler # 4 ;Gallery's event handler
2145 vw__shape # 4 ;Shape handler function
2146 vw__banner # 4 ;Pointer to banner string
2147 vw__fixedWidth # 4 ;Width of banner/title
2148
2149 ; --- Icon sizing information ---
2150
2151 vw__icons # 4 ;Cache number of icons
2152 vw__stdDimens # 8 ;`Standard' width and height
2153 vw__iconWidth # 4 ;Width of icons currently
2154 vw__iconHeight # 4 ;Height of icons currently
2155 vw__across # 4 ;Number of icons across
2156 vw__down # 4 ;Number of icons down
2157
2158 ; --- Data for default selection model ---
2159
2160 vw__tempSel # 4 ;Temporary selected icon
2161
2162 ; --- Big buffers at the end ---
2163
2164 vw__title # 256 ;Title bar buffer
2165
2166 vw__size # 0 ;Size of a viewer block
2167
2168 ; --- Flags bits ---
2169 ;
2170 ; Gallery `borrows' top-end flags bits here
2171
2172 vwFlag__opened EQU (1<<0) ;Has the window been opened?
2173
2174 ;----- Constants ------------------------------------------------------------
2175
2176 vw__iconGap EQU 16 ;Gap between icons
2177 vw__banHeight EQU 48 ;Height of viewer banner
2178
2179 vw__minWidth EQU 380 ;Minimum width for a viewer
2180 vw__minHeight EQU 160 ;Minimum height
2181
2182 vw__titleAdd EQU 164 ;Fudge factor to add to title
2183 vw__banAdd EQU 64 ;Fudge factor for the banner
2184
2185 vw__maxWidth EQU 900-vw__iconGap ;Maximum width of a viewer
2186 vw__maxHeight EQU 700-vw__iconGap ;Maximum height of a viewer
2187
2188 ;----- List definition format -----------------------------------------------
2189
2190 ^ 0
2191 vw__itemToIndex # 4 ;Item to index routine
2192 ;Entry: R0 == pointer to list
2193 ; R1 == pointer to item
2194 ;Exit: R1 == index, or -1
2195
2196 vw__indexToItem # 4 ;Index to item routine
2197 ;Entry: R0 == pointer to list
2198 ; R1 == index of item
2199 ;Exit: R1 == item ptr, or 0
2200
2201 vw__enumerate # 4 ;Enumeration function
2202 ;Entry: R0 == list pointer
2203 ; R1 == item, or 0
2204 ; R2 == BIC mask
2205 ; R3 == test mask
2206 ;Exit: CS if match, and
2207 ; R1 == item ptr
2208
2209 vw__items # 4 ;Function to return items
2210 ;Entry: R0 == list pointer
2211 ;Exit: R1 == number of items
2212
2213 vw__setFlags # 4 ;Function to set/read flags
2214 ;Entry: R1 == pointer to item
2215 ; R2 == BIC mask
2216 ; R3 == EOR mask
2217 ;Exit: R2 == new flags
2218
2219 ;----- Shape function reason codes ------------------------------------------
2220
2221 ^ 0
2222 vwShape_size # 1 ;Read an icon's size
2223 ;Entry: R1 == list item
2224 ; R2,R3 == std size
2225 ;Exit: R2,R3 == actual size
2226
2227 vwShape_intersects # 1 ;Does icon intersect box?
2228 ;Entry: R1 == list item
2229 ; R2 == ptr to icon box
2230 ; R3 == ptr to box
2231 ;Exit: CS if intersect
2232
2233 vwShape_slowBit # 1 ;Does slow bit need redraw?
2234 ;Entry: R1 == list item
2235 ; R2 == ptr to icon box
2236 ; R3 == ptr to box
2237 ;Exit: CS if intersect
2238
2239 ;----- Viewer event codes ---------------------------------------------------
2240
2241 ^ 0
2242 vwEvent_close # 1 ;User has closed the window
2243
2244 vwEvent_click # 1 ;User has clicked an icon
2245 ;R1 == icon handle (or 0)
2246 ;R2 == mouse status
2247
2248 vwEvent_double # 1 ;User has double-clicked
2249 ;R1 == icon handle (or 0)
2250 ;R2 == mouse status
2251
2252 vwEvent_drag # 1 ;User has dragged the mouse
2253 ;R1 == icon handle (or 0)
2254 ;R2 == mouse status
2255
2256 vwEvent_menu # 1 ;User has clicked menu
2257 ;R1 == icon handle (or 0)
2258 ;R2 == mouse status
2259
2260 vwEvent_redraw # 1 ;Redraw a viewer icon
2261 ;R1 == icon handle
2262 ;R2 == pointer to coords blk
2263 ;R3 == pointer to clip blk
2264 ;R5,R6 == window origin
2265
2266 vwEvent_drop # 1 ;File dropped on the viewer
2267 ;R1 == filetype of data
2268 ;R2 == estimated size
2269 ;R3 == address of filename
2270 ;R4 == drop type
2271
2272 vwEvent_help # 1 ;Help request for the viewer
2273 ;R1 == icon handle, or 0
2274
2275 vwEvent_key # 1 ;Key pressed
2276 ;R1 == key code (translated)
2277 ;Return CS if used, else CC
2278
2279 vwEvent_dragged # 1 ;Icons dropped on a window
2280 ;R1 == destination window
2281 ;R2 == destination icon
2282
2283 vwEvent_sprite # 1 ;Return sprite name to use
2284 ;Entry: R1 == icon handle
2285 ; (-1 for many)
2286 ;Exit: CS if sprite found,
2287 ; R0 == ptr to spr area
2288 ; R1 == pointer to name
2289 ; else CC
2290
2291 vwEvent_open # 1 ;The viewer has been moved
2292 ;R1 == ptr to open/state blk
2293
2294 vwEvent_draw # 1 ;Slowly redraw icon
2295 ;R1 == icon handle
2296 ;R2 == pointer to coords blk
2297 ;R3 == pointer to clip blk
2298 ;R5,R6 == window origin
2299 ;(Event only used by gallery)
2300
2301 vwEvent_unDraw # 1 ;Undraw temporary part
2302 ;R1 == icon handle
2303 ;R2 == pointer to coords blk
2304 ;R3 == pointer to clip blk
2305 ;R5,R6 == window origin
2306 ;(Event only used by gallery)
2307
2308 ; --- Drop event subreason codes ---
2309
2310 ^ 0
2311 vwDrop_save # 1 ;File from another app
2312 vwDrop_load # 1 ;File from filing system
2313
2314 ;----- That's all, folks ----------------------------------------------------
2315
2316 END