Home » Archimedes archive » Micro User » MU 1991-03.adf » PD-Stuff » Utilities/Bins/!Trash/source_arc/TrashSrc
Utilities/Bins/!Trash/source_arc/TrashSrc
This website contains an archive of files for the Acorn Electron, BBC Micro, Acorn Archimedes, Commodore 16 and Commodore 64 computers, which Dominic Ford has rescued from his private collection of floppy disks and cassettes.
Some of these files were originally commercial releases in the 1980s and 1990s, but they are now widely available online. I assume that copyright over them is no longer being asserted. If you own the copyright and would like files to be removed, please contact me.
| Tape/disk: | Home » Archimedes archive » Micro User » MU 1991-03.adf » PD-Stuff |
| Filename: | Utilities/Bins/!Trash/source_arc/TrashSrc |
| Read OK: | ✔ |
| File size: | 15919 bytes |
| Load address: | 0000 |
| Exec address: | 0000 |
File contents
10REM >$.!Trash.TrashSrc
20
30REM RISC OS Trash Can Module V1.40 (C) Richard K. Lloyd 1990
40
50REM This source code is released into the Public Domain for anyone to
60REM use, although some credit in your source might be nice...
70
80REM Special thanks to:
90REM - Philip Colmer (PColmer@uk.co.acorn) for suggestions
100REM - Rabin Ezra (rabin@uk.ac.qmc.cs) for bug fixes
110REM - David Pilling (mcbmsdp@uk.ac.mcc.cms) for a beta-test Spark 2.00
120REM - Gary Bartlett () for the Trash Van inspiration and sprites
130REM - Me (rkl@uk.ac.liv.cs.and) for filling a gaping hole in the Desktop
140
150REM Volume/page references are for the RISC OS Issue 1 (1989)
160REM 4-volume Programmer's Reference Manuals.
170
180REM Version 1.40 Released September 1990
190REM - Context-sensitive !Help information provided.
200REM - "Persistent" menu if right button pressed on a menu item.
210REM - New sprites with a Spark-like "flash" - shown if Spark installed.
220REM - Now "Spark-aware" regardless of installation order.
230REM - Incorrect border flash when clicking instead of dragging now fixed.
240
250REM Version 1.30 Released July 1990
260REM - Configuration of new menu options (see below) stored in CMOS RAM.
270REM - 'Immediate' menu option to erase files straight away on a trashing.
280REM - 'Warning' menu option to turn the border red during dangerous ops.
290REM - 'Animation' menu option to show an icon bar Van during deletion.
300REM - New VanSprites file (and code to handle it) for above animation.
310REM - Fixed Info template workspace fault (force reload after Temp Quit).
320REM - Auto-time/datestamp updating of Info window without using !Formed.
330REM - Added, ahem, a "debug%" flag for window/icon handle display.
340REM - 'Immediate' mode now accidentally simulates the behaviour of an
350REM Atari ST trash can ! In other words, no fat icon, no Trash Window,
360REM no retention of trashed files in Trash$Dir. Pretty rubbish (!) eh ?
370
380REM Version 1.20 Released January 1990
390REM - Report errors if any occur during the trashing/emptying processes.
400REM - Switch on hourglass if trashing takes longer than 1 second.
410REM - Supports file trashing from inside archives using Spark 2.xx.
420REM - Displays an error if *Desktop_TrashCan issued outside the Desktop.
430
440REM Version 1.11 Released November 1989 (2 days after V1.10 !)
450REM - Fixed *fatal* bug with V1.10 Info menu item.
460REM - Slightly re-coded Quit menu parsing.
470REM - Adjusted menu widths and heights (Philip Colmer).
480REM - Allowed Info window to be dragged (Philip Colmer).
490
500REM Version 1.10 Released November 1989
510REM - Enhancements by Philip Colmer from 1.02a:
520REM - Third sprite added to overcome trash can 'love-handles' in Filer.
530REM - Correction of icon bar parameter block (wildly wrong in 1.02).
540REM - Hard-coded Info window replaces cheap sub-menu Info.
550REM - Enhancements by RKL on top of this:
560REM - Uses Templates for Info window (boy, do I hate !FormEd...).
570REM - New Temporary/Permanent Quit menu option.
580REM - Claims RMA during module life for internal workspace.
590REM - Set TrashWork$Dir to <Obey$Dir> in !Run (template/sprites dir).
600REM - Performs internal *IconSprites call (Wimp_SpriteOp 11).
610
620REM Version 1.02a - not released (Modifications by Philip Colmer)
630
640REM Version 1.02 Released November 1989
650REM - Had to redefine !Trash sprite because of Wimp_SetIconState.
660REM - Bug fixes (including code) by Rabin Ezra:
670REM - Extended Trash$Dir buffer to 64 chars.
680REM - Checked for Trash$Dir expansion buffer overflow.
690REM - Zero-terminated the Trash$Dir expansion.
700REM - Improvement suggestions (with coding hints) by Philip Colmer:
710REM - Moved Trash Can icon to left side of icon bar.
720REM - Improved filing system activity trapping.
730REM - Stopped annoying icon bar "icon shuffling".
740
750REM Version 1.01 Released July 1989
760REM - Fixed rename inconsistency.
770REM - Added Wimp_Poll message acknowledgement.
780REM - Extended maximum length of expanded Trash$Dir to 48 chars.
790REM - Set Trash$Dir to <Obey$Dir>.Trash in !Run.
800REM - Posted with Acorn's "official" uuencode to avoid IBM munging.
810
820REM Version 1.00 Released July 1989
830REM - Mac-style trash can with Mac-style icons (ResEdit was useful !).
840REM - Survives anything except hard reset, module kill or power off.
850
860REM Check out the Indigo Girls' eponymously-titled album (on CD):
870REM great acoustic guitar harmonies - reached US #22 (sadly nowhere in UK)
880REM RKL's Best Album Of 1989: Diesel Park West's "Shakespeare Alabama" CD.
890REM RKL's Best Albums Of 1990 so far:
900REM All those Beach Boys 2-for-1 CD reissues - great stuff !
910
920DIM org &2000:REM Plenty of assembly space
930
940REM Application constants
950
960prog$="Trash Can":REM English text name of module
970ver$="1.40":REM Version number of module in X.YY format
980REM Change next line to date$=MID$(TIME$,5,11) to get the current date
990date$="10 Sep 1990":REM Current date as a fixed string
1000resdate$=LEFT$(date$,2)+"-"+MID$(date$,4,3)+"-"+RIGHT$(date$,2)
1010resdate$=ver$+" ("+resdate$+")":REM Version/date for Info Template
1020command$="Desktop_TrashCan":REM * command implemented
1030trashvar$="Trash$Dir":REM Trash can environmental variable
1040wimp$="Wimp$Scrap":REM Wimp temporary file environmental variable
1050maxpathlen%=64:REM Maximum length of expanded Trash$Dir (inc. terminator)
1060iconbartype%=-2:REM -1 = Utility (RHS of bar), -2 = Service (LHS of bar)
1070windman%=200:REM Expect at LEAST V2.00 of the Window Manager
1080stackspace%=&800:REM 2K for internal RMA stack and template workspace
1090windowspace%=&800:REM 2K for Wimp_GetWindowInfo / Wimp_TransferBlock
1100spritespace%=3*1024:REM 3K for sprite user area
1110sparkdel$="!spark -d ":REM Spark command to delete a file inside archive
1120battery%=38:REM CMOS RAM location used to store settings
1130debug%=FALSE:REM So-called debugging - prints window/icon handle
1140
1150REM Time for some constants to help the reader
1160
1170bl$=CHR$(0):REM NULL char used to terminate strings
1180cr$=CHR$(13):REM Plain CR
1190UpCallV=&1D:REM Warning vector for FS change check
1200XOS_WriteI=&20100:REM X SWI form of OS_WriteI (used for VDU 7). I-199
1210
1220Service_Reset =&27:REM End of machine reset signalled
1230Service_StartWimp =&49:REM Request by Desktop to start WIMP modules
1240Service_StartedWimp=&4A:REM Desktop indicates all tasks now active
1250
1260FOR A%=0 TO 2 STEP 2
1270P%=org
1280[OPT A%
1290
1300; Note that the module header must contain ADDRESS OFFSETS from the
1310; start of the module, hence a subtraction of org is required. II-628
1320
1330 EQUD appstart-org ; Application start addr
1340 EQUD init-org ; Initialisation addr
1350 EQUD byebye-org ; Finalisation addr
1360 EQUD servicecall-org ; Service call handler addr
1370 EQUD titlestr-org ; Module title string addr
1380 EQUD helpstr-org ; Help string addr
1390 EQUD keywords-org ; Command/help table addr
1400 EQUD 0 ; No extra SWIs...
1410 EQUD 0 ; What do you want ?
1420 EQUD 0 ; Blood ?
1430 EQUD 0 ; Well hard luck...
1440
1450; Title string to be used by *Modules and when *RMKilling etc. II-635
1460; Due to the way *Help works in RISC OS, avoid calling the module the
1470; same name as one of its * commands (I've been guilty of this ...!).
1480
1490.titlestr EQUS "TrashCan"+bl$
1500 ALIGN
1510
1520; Help string to be used in *Help Modules etc. II-635
1530; Note the tab character as recommended by Acorn. A second tab
1540; character will be needed if prog$ is < 8 characters (unlikely !).
1550
1560.helpstr EQUS prog$+CHR$(9)+ver$+" ("+date$+")"+bl$
1570 ALIGN
1580
1590; Keyword lookup table for *Help and command execution. II-636
1600; Any addresses should, as usual, be offsets from the module start.
1610; Note- Modules that multi-task under the Wimp MUST have a startup
1620; * command because of the way Start_WimpTask is called when
1630; the Desktop first starts up.
1640
1650.keywords
1660.startupname EQUS command$+bl$ ; * command name
1670 ALIGN ; MUST include an ALIGN
1680 EQUD startupcomm-org ; TrashCan exec addr OFFSET
1690 EQUB 0 ; Minimum params = 0
1700 EQUB %00000000 ; No OS_GSTrans peformed
1710 EQUB 0 ; Maximum params = 0
1720 EQUB %00000000 ; No *Conf or special *Help code
1730 EQUD noparams-org ; Special params message OFFSET
1740 EQUD startuphelp-org ; * command help text OFFSET
1750 EQUD 0 ; No more * commands
1760
1770; If any parameters supplied, then complain. In actual fact, this message
1780; is displayed if params<min or params>max (just that min=max=0 here).
1790
1800.noparams EQUS "Syntax: *"+command$+bl$
1810 ALIGN
1820
1830; *Help text goes here. Avoid CHR$(13) or CHR$(10) unless absolutely
1840; necessary (usually to split the *Syntax message from the rest),
1850; because this text is OS_PrettyPrinted. Hard spaces = CHR$(31).
1860
1870.startuphelp EQUS "The "+prog$+" utility provides a trash can icon on the icon bar, and uses "
1880 EQUS "the Filer to display the trash can contents."+cr$+CHR$(10)+"Do not use *"+command$+", use *Desktop instead."+bl$
1890 ALIGN
1900
1910; PHEW ! Now let's get down to some coding...
1920
1930.internalreset
1940
1950; An internal task variable is set to zero (not running) on execution
1960; of the Initialisation code, at the end of a machine (soft !) reset or
1970; when an old task is shutdown (to prevent duplication).
1980
1990 STMFD R13!,{R0,R14}
2000 MOV R0,#0
2010 STR R0,taskhandle ; Task not running, not claimed
2020 STR R0,sparktaskhand; Don't know about Spark yet
2030 STR R0,sparkwindhand; or the window involved
2040 STRB R0,glassstat ; Hourglass is off
2050 LDMFD R13!,{R0,PC}
2060
2070.servicecall
2080
2090; The location 'taskhandle' holds the state of the task:
2100; 0 = Not running, waiting to claim Service_StartWimp
2110; -1 = Not running, claimed Service_StartWimp, waiting for * command
2120; >0 = Running, value set to Wimp_Initialise returned task handle
2130
2140; The Service_Reset signal (Service Call &27) is the ONLY way (I know..)
2150; to execute module code at the end of a machine reset. I use this to
2160; shutdown the task if still active.
2170; II-681 ---> DOESN'T TELL YOU to refer to III-1161
2180
2190 CMP R1,#Service_Reset ; End of machine reset ?
2200 BEQ init ; Yes, so restart
2210
2220; The very first thing that the Desktop does after a Wimp_Initialise
2230; is to signal Service_StartWimp (Service Call &49) to every module.
2240; Those that are interested in being trendy (OK, multi-tasking), claim
2250; that service call IF THEY ARE NOT ALREADY RUNNING and, of course,
2260; haven't already received and claimed a Service_StartWimp.
2270; II-701 ---> annoyingly referring to the rough 'Window Manager' chapter
2280; (turns out, after much page scanning, to be III-1159)
2290
2300 CMP R1,#Service_StartWimp ; Are we firing up the
2310 BEQ round1 ; Desktop ?
2320
2330; Once everyone's responded to Service_StartWimp who wants to, a
2340; 'final chance' is sent around - Service_StartedWimp (&4A).
2350; II-702 ---> annoyingly (vaguely, like above) referring to III-1161
2360
2370 CMP R1,#Service_StartedWimp ; Round 2 of Desktop
2380 BEQ round2
2390
2400 MOV PC,R14 ; Not interested in any of them
2410
2420.round1 STMFD R13!,{R2,R14}
2430 LDR R2,taskhandle
2440 MOVS R2,R2 ; Is taskhandle = 0 ?
2450 MVNEQ R2,#0 ; Yes, so taskhandle = -1
2460 STREQ R2,taskhandle
2470; Claim the Service Call because not running and not prev. claimed it
2480 ADREQ R0,startupname ; => *Desktop_Trashcan
2490 MOVEQ R1,#0 ; Claim the call
2500 LDMFD R13!,{R2,PC}
2510
2520.round2
2530
2540; Since the * command may have failed, the task handle should be
2550; set to 0 if it's still stuck at -1.
2560
2570 STMFD R13!,{R2,R14}
2580 LDR R2,taskhandle
2590 MOVS R2,R2 ; Is taskhandle = -1 ?
2600 MOVMI R2,#0 ; Stuck, so unstick !
2610 STRMI R2,taskhandle
2620 LDMFD R13!,{R2,PC}
2630
2640.claimRMA
2650
2660; On entry, R3 = RMA space required
2670; On exit, R2 = Pointer to claimed space
2680
2690 STMFD R13!,{R0,R14}
2700 MOV R0,#6 ; Claim RMA
2710.joinclaim SWI "XOS_Module" ; II-655
2720 ADRVS R0,poorclaim
2730 SWIVS "OS_GenerateError" ; I-41
2740 LDMFD R13!,{R0,PC}
2750.poorclaim EQUD 0
2760 EQUS "RMA workspace failure"+bl$
2770 ALIGN
2780
2790.releaseRMA
2800
2810; On entry, R2 = Pointer to space to be released
2820
2830 STMFD R13!,{R0,R14}
2840 MOV R0,#7 ; Release RMA
2850 B joinclaim
2860
2870.startupcomm
2880
2890; Once Service_WimpStart has been claimed, the Desktop will call
2900; Wimp_StartTask with R0 = * command addr returned by the claimant.
2910; Unfortunately, you can't dive straight in and start executing your
2920; code - you have to call OS_Module 2 (Enter Application) first.
2930
2940 STMFD R13!,{R0-R2,R14}
2950 MOV R2,R0 ; Point to * command tail
2960 MOV R0,#0 ; How many tasks running ?
2970 SWI "XWimp_ReadSysInfo" ; III-1284
2980 MOVS R0,R0 ; None, so not in
2990 ADREQ R0,notindesktop ; Desktop
3000 SWIEQ "OS_GenerateError"
3010 ADR R1,titlestr ; Point to module name
3020 MOV R0,#2 ; Enter Application
3030 SWI "XOS_Module" ; II-651
3040 LDMFD R13!,{R0-R2,PC}
3050.notindesktop EQUD 0
3060 EQUS "Use *Desktop to start the "+prog$+bl$
3070 ALIGN
3080
3090.leavenow
3100
3110; User-instigated quit requested, so shutdown task and leave gracefully
3120; On entry, R9 = 0 for Temporary Quit, 1 for Permanent Quit
3130; = -1 for main (rather than sub) menu Quit
3140; For the moment, R9 = -1 is treated as a Permanent Quit (happy Philip ?)
3150
3160 BL wimpclosedown ; All done, so shutdown
3170 MOVS R9,R9 ; Severity of Quit ?
3180 MOVEQ R1,#0
3190 MOVEQ R2,#0
3200 SWIEQ "OS_Exit" ; 0 = Mild ! II-743
3210 ADR R0,trashname1 ; First name
3220 MVN R2,#0 ; Delete variables
3230 MOV R3,#0 ; First call
3240 MOV R4,#0 ; Normal string
3250 SWI "XOS_SetVarVal" ; Delete Trash$Dir. II-752
3260 ADR R0,trashname2 ; Second name
3270 MOV R3,#0 ; First call
3280 MOV R4,#0 ; Normal string
3290 SWI "XOS_SetVarVal" ; Delete TrashWork$Dir
3300 MOV R0,#0
3310 MOV R1,#0
3320 MOV R2,#0
3330 ADR R3,titlestr
3340 SWI "OS_ExitAndDie" ; -1 or 1 = Severe ! II-758
3350.trashname1 EQUS "Trash$Dir"+bl$
3360.trashname2 EQUS "TrashWork$Dir"+bl$
3370 ALIGN
3380
3390.registerspark
3400
3410; On entry, R5 = Spark's "new" task handle
3420
3430 STMFD R13!,{R0,R14}
3440 LDR R0,sparktaskhand; Get old task handle
3450 CMP R0,R5 ; Is it new info ?
3460 STRNE R5,sparktaskhand; Save new task handle
3470 BLNE redocontents ; Update trash can icon
3480 LDMFD R13!,{R0,PC}
3490
3500.inituserarea
3510
3520; After about 75 million different attempts at coding using OS_SpriteOp
3530; only, OS_SpriteOp mixed with Wimp_SpriteOp and Wimp_SpriteOp only,
3540; I came to following conclusions regarding Wimp programs and sprites:
3550; 1) Use Wimp_SpriteOp for reading Sprite files and plotting them.
3560; 2) Use OS_SpriteOp 16 for saving a rect to a sprite (saves background)
3570; and OS_SpriteOp 34 for replotting that saved rect
3580; 3) Setup RMA workspace (claim and then call OS_SpriteOp 9) for the
3590; OS_SpriteOp 16/34 calls - do NOT use the System Sprite area !
3600
3610 STMFD R13!,{R0,R1,R14}
3620 MOV R0,#spritespace%; Space needed for Van sprites
3630 LDR R1,spritearea ; Offset 0 = Total area size
3640 STR R0,[R1]
3650 MOV R0,#0 ; Offset 4 = No sprites yet
3660 STR R0,[R1,#4]
3670 MOV R0,#16
3680 STR R0,[R1,#8] ; Offset 8 = No extension area
3690 STR R0,[R1,#12] ; Offset 12 = First free word
3700 MOV R0,#9 ; Initialise sprite area (*SNew)
3710 BL spriteop ; I-398
3720 LDMFD R13!,{R0,R1,PC}
3730
3740.dummyspark STMFD R13!,{R3,R14}
3750 LDR R3,sparktaskhand ; Only send if Spark's
3760 MOVS R3,R3 ; handle unknown
3770 LDREQ R3,windowspace ; Point to start of command
3780 ADDEQ R3,R3,#20 ; buffer
3790 BLEQ sendittospark ; Tell everyone to do nothing
3800 LDMFD R13!,{R3,PC}
3810
3820.delsparkfile STMFD R13!,{R0,R2,R3,R14}
3830 ADR R0,savedleaf
3840 LDR R3,putleafhere ; Set up when drag started
3850.retrieveleaf LDRB R2,[R0],#1 ; Copy leaf onto end
3860 STRB R2,[R3],#1
3870 MOVS R2,R2
3880 BNE retrieveleaf
3890 BL sendittospark ; Tell Spark to delete file
3900 LDMFD R13!,{R0,R2,R3,PC}
3910
3920.sendittospark STMFD R13!,{R0-R3,R14}
3930 MOV R0,#13 ; Needs CR at end of command
3940 STRB R0,[R3],#1
3950 MOV R0,#0
3960.padtoword STRB R0,[R3],#1
3970 TST R3,#%11 ; Pad to word
3980 BNE padtoword
3990 LDR R1,windowspace
4000 SUB R0,R3,R1 ; Size (inc. leaf/data) of block
4010 LDR R2,sparktaskhand
4020 LDR R3,sparkcommID ; Spark command message ID
4030 BL sendamessage
4040 LDMFD R13!,{R0-R3,PC}
4050.sparkcommID EQUD &41000+61 ; Do Spark command ID
4060
4070.sendamessage
4080
4090; On entry, R0 = Size of message block
4100; R1 = Pointer to message (usu. Wimp_Poll) block
4110; R2 = Task handle (0 = everyone)
4120; R3 = Message action
4130
4140 STMFD R13!,{R0,R14}
4150 STR R0,[R1] ; Store block length
4160 MOV R0,#0
4170 STR R0,[R1,#12] ; my_ref = 0 (Original message)
4180 STR R3,[R1,#16] ; Store message action
4190 MOV R0,#18
4200 SWI "XWimp_SendMessage" ; III-1253
4210 LDMFD R13!,{R0,PC}
4220
4230.appstart
4240
4250; Well, here's the start sequence at last ! We only want one of this
4260; task running, so must shut down the old one if it is running.
4270
4280 LDR R13,workspace ; Reset stack pointer -> RMA
4290 BL wimpclosedown ; Shut down old task
4300 MOV R0,#windman% ; Expecting V2.00 Window Manager
4310 LDR R1,taskconstant ; Indicate new-style Wimp task
4320 ADR R2,description ; English text name of program
4330 SWI "XWimp_Initialise" ; Start task. III-1173
4340 CMP R0,#windman% ; Are we earlier than V2.00 ?
4350 ADRLT R0,notrecentwimp; Yes, so crash out
4360 SWILT "OS_GenerateError"
4370 STR R1,taskhandle ; Save Wimp task handle
4380
4390; At the point, everything is ready for application initialisation...
4400
4410 BL dummyspark ; Try and get Spark to reply
4420 BL loadtemplate ; Load template/make Info window
4430 BL scantrashspr ; Load application sprites
4440 BL readCMOS ; Setup menu ticks
4450 MOV R10,#0 ; First scan
4451 STRB R10,dragstate ; Assume button is up
4460 BL checkcontents ; Scan trash can
4470 BL scanvanspr ; Load animation sprites
4480
4490; Because applications could rename/delete/copy etc. in a variety of
4500; ways (and not using the WIMP), then have to claim UpCallV to
4510; trap any directory-changing activity.
4520
4530 MOV R0,#UpCallV ; I-68
4540 ADR R1,trapupcall
4550 MOV R2,#0
4560 SWI "XOS_Claim" ; I-58
4570
4580; ...and a tight Wimp_Poll loop, only quitting when the user requests it
4590
4600.intightloop MOV R0,#0 ; All reason codes wanted
4610 SUB R1,R13,#stackspace% ; Data returned to RMA
4620 SWI "XWimp_Poll" ; III-1192
4630 LDR R13,workspace ; Reset stack pointer -> RMA
4640 MOVS R0,R0 ; Is it idle ?
4650 BNE actuallybusy
4660 BL stopglass ; Yes, so Hourglass off if on
4670 BL checkfordrag ; Are we dragging from Spark ?
4680 B checkfsflag ; See if Trash$Dir has changed
4690.actuallybusy CMP R0,#6 ; Check for mouse click. III-1196
4700 BNE maybemenusel
4710 LDR R0,[R1,#8] ; Get button state
4720 CMP R0,#4 ; Is it left button...?
4730 CMPNE R0,#1 ; ...or the right button ?
4740 BNE maybemiddle
4750 LDRB R0,CMOSbyte ; Only do something if not in
4760 TST R0,#%001 ; Immediate mode
4770 BLEQ peepincan ; Look inside trash can
4780 B intightloop
4790.maybemiddle CMP R0,#2
4800 BLEQ makenewmenu ; Middle button -> menu
4810 B intightloop
4820.maybemenusel CMP R0,#9
4830 BNE nomouseclick
4840 MOV R2,R1 ; Save Wimp_Poll block ptr
4850 ADD R1,R1,#&100 ; Pointer block further on
4860 SWI "XWimp_GetPointerInfo" ; III-1214
4870 LDR R0,[R1,#8] ; Get button state
4880 MOV R1,R2 ; Restore Wimp_Poll block ptr
4890 BL dealwithmenu ; Menu item selected. III-1199
4900 CMP R0,#1 ; Is it the right button ?
4910 BLEQ makeoldmenu ; Keep menu on screen
4920 B intightloop
4930.nomouseclick CMP R0,#2 ; Info window dragged ?
4940 BNE maybemessage ; (Philip Colmer)
4950 SWI "XWimp_OpenWindow" ; III-1190
4960 B intightloop ; That was nice'n'easy...
4970.maybemessage CMP R0,#17 ; Check for message broadcast
4980 CMPNE R0,#18 ; III-1202
4990 BNE checkfsflag
5000 LDR R2,[R1,#16]
5010 MOVS R2,R2
5020 MOVEQ R9,#0 ; Signal Temporary Quit
5030 BEQ leavenow ; Quit requested. III-1255
5040 MOV R3,#&500
5050 ADD R3,R3,#2 ; !Help ID = &502
5060 CMP R3,R2 ; Was !Help requested ?
5070 BNE wasitadrag
5080 LDR R2,[R1,#32] ; Get icon handle
5090 CMN R2,#-iconbartype% ; Icon bar ?
5100 MOVNE R4,#1 ; No, so must be Info Window
5110 BNE helpwanted ; Rejoin help request
5120 LDR R2,[R1,#36] ; Is it my icon ?
5130 LDR R3,iconhandle
5140 CMP R2,R3
5150 BNE intightloop
5160 MOV R4,#0 ; Flag that it's the icon
5170.helpwanted BL askedforhelp ; !Help info requested
5180 B intightloop
5190.wasitadrag CMP R2,#3 ; Load data requested ?
5200 BNE maybespark ; III-1265
5210 LDR R2,[R1,#20] ; Is it on the icon bar ?
5220 CMN R2,#-iconbartype%
5230 BNE intightloop
5240 LDR R2,[R1,#24] ; Is it my icon ?
5250 LDR R3,iconhandle
5260 CMP R2,R3
5270 BLEQ moveintotrash ; File dragged onto trash can
5280 B intightloop
5290.maybespark LDR R3,dyingappmess ; Has an application just died ?
5300 LDR R4,sparktaskhand
5310 LDR R5,[R1,#4] ; Get task handle involved
5320 CMP R2,R3
5330 CMPEQ R5,R4 ; Was it Spark ?
5340 MOVEQ R5,#0 ; If so, forget Spark's handle
5350 BEQ sparkchange ; Return icon to normal
5360 LDR R3,reptaskname ; Is it the task handle
5370 CMP R2,R3 ; translation ?
5380 BNE didsparkstart
5390 ADR R0,sparktaskname; Spark's task name...
5400 ADD R2,R1,#28
5410.scanningname LDRB R3,[R0],#1 ; ...compare it with the
5420 LDRB R4,[R2],#1 ; returned name to find a match
5430 CMP R3,R4
5440 BNE intightloop
5450 MOVS R3,R3 ; Still scanning name
5460 BNE scanningname
5470 LDR R5,[R1,#20] ; Retrieve handle matching name
5480 B sparkchange
5490.didsparkstart LDR R3,sparkmessid ; Has Spark just started up ?
5500 CMP R2,R3
5510 BEQ sparkchange ; OK, time to know about Spark
5520 LDR R3,sparkcommID ; Was Spark replying ?
5530 CMP R2,R3
5540 BNE whataboutsave ; Not a response to dummy bcast
5550; At this point, received response from dummy Spark broadcast, so ask
5560; about the name matching the task handle (in R5 at the moment)
5570 MOV R0,#24 ; Size = 24 bytes
5580 MOV R2,#0 ; General broadcast
5590 LDR R3,reqtaskname ; Request task handle translation
5600 STR R5,[R1,#20] ; Store task handle
5610 BL sendamessage
5620 B intightloop
5630.whataboutsave CMP R2,#1 ; DataSave request ?
5640 BNE intightloop ; (Spark'ed file onto Trash Can)
5650 CMP R4,R5 ; Check task handle involved
5660 BNE intightloop ; belongs to Spark and no-one else
5670 MOV R2,R4
5680 LDR R3,[R1,#8] ; Copy my_ref
5690 STR R3,[R1,#12]
5700 MOV R3,#2 ; DataSaveAck
5710 STR R3,[R1,#16]
5720 MVN R3,#0 ; Set file to 'unsafe' (-1)
5730 STR R3,[R1,#36]
5740 ADD R3,R1,#44
5750 ADR R4,savedleaf
5760.savetheleaf LDRB R5,[R3],#1 ; Save suggested Spark
5770 STRB R5,[R4],#1 ; leafname for use later
5780 MOVS R5,R5
5790 BNE savetheleaf
5800 ADR R3,tempsparkname
5810 ADD R4,R1,#44
5820.copyscrapname LDRB R5,[R3],#1 ; Temporary filename for
5830 STRB R5,[R4],#1 ; decompression = <Wimp$Scrap>
5840 MOVS R5,R5
5850 BNE copyscrapname
5860 SWI "XWimp_SendMessage" ; Spark->decompress
5870 B intightloop
5880.sparkchange BL registerspark ; Save Spark handle if changed
5890 BL dummyspark ; Re-broadcast in case there's
5900 B intightloop ; 2 or more Sparks...
5910.sparkmessid EQUD &41000+60 ; Spark started message ID
5920.dyingappmess EQUD &400C3 ; Message_TaskCloseDown
5930.reqtaskname EQUD &400C6 ; Message_TaskNameRq
5940.reptaskname EQUD &400C7 ; Message_TaskNameIs
5950.tempsparkname EQUS "<"+wimp$+">"+bl$
5960 ALIGN
5970.sparktaskname EQUS "Spark"+bl$
5980 ALIGN
5990
6000.checkfsflag LDRB R10,fsctrlflag ; This is why we need all reason
6010 MOVS R10,R10 ; codes - at any time there could
6020 BLNE checkcontents ; be an FS action changing
6030 B intightloop ; Trash$Dir
6040
6050.description EQUS prog$+bl$
6060 ALIGN
6070.sparktaskhand EQUD 0
6080.sparkwindhand EQUD 0
6090.notrecentwimp EQUD 0
6100 EQUS prog$+" requires Window Manager V"+FNfraction(windman%)+" or later"+bl$
6110 ALIGN
6120
6130.init
6140
6150; This routine is called when the module is first loaded, when a
6160; *RMReInit is called or when a machine reset is signalled.
6170
6180 STMFD R13!,{R2,R3,R14}
6190 BL internalreset ; Only want to reset
6200 MOV R3,#stackspace% ; Claim RMA for stack
6210 LDR R2,workspace ; See if already claimed
6220 MOVS R2,R2
6230 BLEQ claimRMA
6240 ADDEQ R2,R2,R3 ; Adjust to end of workspace
6250 STREQ R2,workspace ; cos stack builds downwards
6260 MOVEQ R3,#windowspace%; Claim RMA for window info
6270 BLEQ claimRMA
6280 STREQ R2,windowspace
6290 MOVEQ R3,#spritespace%; Claim RMA for sprite workspace
6300 BLEQ claimRMA
6310 STREQ R2,spritearea
6320 LDMFD R13!,{R2,R3,PC}
6330.workspace EQUD 0
6340.windowspace EQUD 0
6350.spritearea EQUD 0
6360.savedleaf EQUS STRING$(11,bl$) ; Filename
6370 ALIGN
6380
6390.changeicon
6400
6410; On entry, R1 = ASC "1" for thin trash can, ASC "2" for thick
6420; This routine has been added to V1.02 onwards
6430; Entry param different in V1.10 onwards for new thin can (Philip Colmer)
6440; Now adds 2 to R1 if Spark's task handle is known
6450
6460 STMFD R13!,{R0,R1,R14}
6470 LDR R0,sparktaskhand; Do we know Spark's handle yet ?
6480 MOVS R0,R0
6490 ADDNE R1,R1,#2 ; Yes, so use 'flashy' sprites
6500 LDRB R0,spritename+6
6510 CMP R0,R1 ; No point in call if no change
6520 STRNEB R1,spritename+6 ; Toggle sprite name
6530 ADRNE R1,iconstateblk
6540; Boy - my favourite opcode is on the next line !
6550 SWINE "XWimp_SetIconState" ; III-1211. Avoid shuffle
6560 LDMFD R13!,{R0,R1,PC}
6570.iconstateblk EQUD iconbartype%
6580.iconhandle EQUD 0
6590 EQUD 0 ; EOR word ; Both words set to zero
6600 EQUD 0 ; Clear word ; because flags the same
6610
6620.makeicon
6630
6640; On entry, R1 = ASC "1" for thin trash can, ASC "2" for thick
6650; Note - Sprites should be called '!trash1' and '!trash2' - do NOT rename
6660; Entry param different in V1.10 onwards for new thin can (Philip Colmer)
6670
6680 STMFD R13!,{R0,R1,R14}
6690 STRB R1,spritename+6 ; Poke name ending
6700 ADR R1,spritename
6710 STR R1,pokespname
6720 ADR R1,iconblock
6730 SWI "XWimp_CreateIcon" ; III-1180
6740 STR R0,iconhandle
6750 LDMFD R13!,{R0,R1,PC}
6760; This is a data block for Wimp_CreateIcon - fixed by Philip Colmer
6770.iconblock EQUD iconbartype% ; Icon bar 'service' flag
6780 EQUD 0 ; Bottom left X
6790 EQUD 0 ; Bottom left Y
6800 EQUD 69 ; Top right X
6810 EQUD 68 ; Top right Y
6820 EQUB %00000010 ; Icon is a sprite
6830 EQUB %00110001 ; Click notifies/Indirected
6840 EQUB %00000000 ; Nothing special about icon
6850 EQUB %00000001 ; Forecol = 1, Backcol = 0
6860.pokespname EQUD 0 ; Pointer to sprite name
6870 EQUD 1 ; Pointer to WIMP sprites
6880 EQUD 12
6890.spritename EQUS "!trash"+STRING$(6,bl$) ; Sprite name
6900
6910; 'killicon' routine removed from V1.02 onwards - no longer required
6920
6930.trapupcall
6940
6950; Thanks to Philip Colmer for the reason codes here - the old PRMs
6960; only list R0=1 and R0=&100, so I had no idea about R0=3 ! I-139
6970; On entry, R0 = Reason code (3 for file modification)
6980; R9 = File modification reason (if R0=3)
6990
7000 STMFD R13!,{R9,R14}
7010 CMP R0,#3 ; Only if modification notified
7020 BNE notfilemod
7030 CMP R9,#0 ; *Save (0)
7040 CMPNE R9,#6 ; *Delete (6)
7050 CMPNE R9,#7 ; *Create (7)
7060 CMPNE R9,#8 ; *CDir (8)
7070 SUB R9,R9,#256 ; Can't get 257 immediately
7080 CMPNE R9,#1 ; Open/Create for update (257)
7090 SUB R9,R9,#256 ; Can't get 520 immediately
7100 CMPNE R9,#8 ; *Rename (520)
7110 MOVEQ R9,#1 ; Although can't be sure, set
7120 STREQB R9,fsctrlflag ; changed flag to be safe
7130.notfilemod LDMFD R13!,{R9,PC}
7140
7150.wimpclosedown
7160
7170; This (handy) routine will only call Wimp_CloseDown if Wimp_Initialise
7180; had successfully been executed (i.e. taskhandle > 0). It then sets
7190; taskhandle to 0 to indicate shutdown. Note that Wimp_CloseDown also
7200; handily kills the icon bar icon.
7210
7220 STMFD R13!,{R0-R2,R14}
7230 LDR R0,taskhandle ; Is taskhandle > 0 ?
7240 MOVS R0,R0
7250 BLE dormanttask
7260 BL notrashwind ; Remove Trash Can Window
7270 MOV R0,#UpCallV ; Release UpCallV
7280 ADR R1,trapupcall
7290 MOV R2,#0
7300 SWI "XOS_Release" ; I-59
7310 BL checkforred ; Remove red border if present
7320 LDR R0,taskhandle
7330 LDR R1,taskconstant
7340 SWI "XWimp_CloseDown" ; Shutdown task. III-1241
7350.dormanttask MOV R0,#0
7360 STR R0,iconhandle ; Clear icon handle
7370 STR R0,taskhandle ; Clear task handle
7380 STR R0,sparktaskhand; Clear Spark handle
7390 STR R0,templatehandle ; Templates will need a reload
7400 STRB R0,modifiedbord ; No red border yet
7410 LDMFD R13!,{R0-R2,PC}
7420.taskconstant EQUS "TASK" ; Special four-letter word !
7430.taskhandle EQUD 0 ; Wimp task handle (also used as a flag)
7440
7450.peepincan
7460
7470; Want to have a look inside trash can, so create the directory if not
7480; already there and use the Filer to create a new Wimp task.
7490
7500 STMFD R13!,{R0,R14}
7510 BL canexists ; Make sure Trash$Dir is OK
7520
7530; Stupid *Filer_OpenDir <dir> doesn't translate environmental vars !!
7540; Hence must use translated buffer.
7550
7560 ADR R0,startupwind
7570 SWI "XWimp_StartTask" ; III-1242
7580 LDMFD R13!,{R0,PC}
7590
7600.readtrashdir
7610
7620; On entry, R1 = Address of buffer to store Trash$Dir expansion
7630; MUST have Trash$Dir defined at all times, otherwise fatal error
7640
7650 STMFD R13!,{R0-R4,R14}
7660 MOV R0,#0
7670 STRB R0,poketrash
7680 ADR R0,plaintrash
7690 MOV R2,#maxpathlen%-1 ; Reduced by 1 (Rabin).
7700 MOV R3,#0
7710 MOV R4,#0
7720 SWI "XOS_ReadVarVal" ; II-750
7730 MOVVC R0,#0
7740 STRVCB R0,[R1,R2] ; Add a zero terminator (Rabin).
7750 LDMVCFD R13!,{R0-R4,PC}
7760; This section revamped by Rabin Ezra. Thanks !
7770 MOVS R2,R2 ; Is error overflow ?
7780 ADREQ R0,undefinedvar
7790 ADRNE R0,vartoolong
7800 SWI "OS_GenerateError"
7810.plaintrash EQUS trashvar$+bl$
7820.startupwind EQUS "Filer_OpenDir " ; III-1292
7830.trashopenbuff EQUS STRING$(maxpathlen%,bl$)
7840.closedownwind EQUS "Filer_CloseDir " ; III-1291
7850.trashclosebuff EQUS STRING$(maxpathlen%,bl$)
7860 ALIGN
7870.vartoolong EQUD 0
7880 EQUS trashvar$+" environmental variable longer than "+STR$(maxpathlen%-1)+" characters"+bl$
7890 ALIGN
7900.undefinedvar EQUD 0
7910 EQUS trashvar$+" environmental variable undefined"+bl$
7920.fsctrlflag EQUB 0
7930.glassstat EQUB 0
7940.CMOSbyte EQUB 0
7941.dragstate EQUB 0
7950 ALIGN
7960
7970.notrashwind STMFD R13!,{R0,R1,R14}
7980 ADR R1,trashclosebuff
7990 BL readtrashdir ; Get Trash$Dir
8000
8010; Note that because the Wimp may already be partially shut down, we
8020; can't use XWimp_StartTask in this section, so use XOS_CLI
8030
8040 ADR R0,closedownwind
8050 SWI "XOS_CLI" ; Shutdown Trash window. II-619
8060 LDMFD R13!,{R0,R1,PC}
8070
8080.checkcontents
8090
8100; On entry, R10 = 0 if want to create icon, <> 0 to update it
8110; Want to decide what icon to put on icon bar, so check the contents
8120; of <Trash$Dir>. If the env. variable doesn't exist, or the dir doesn't
8130; exist or there's nothing in the dir, then trash is empty.
8140
8150 STMFD R13!,{R0-R3,R14}
8160 ADR R1,trashopenbuff
8170 BL readtrashdir ; Trash$Dir check
8180 MOV R0,#ASC"."
8190 STRB R0,poketrash
8200 MOV R0,#5
8210 ADR R1,trashbits
8220 SWI "XOS_File" ; Any <Trash$Dir>.* files ? III-850
8230 LDR R2,trashstat
8240 ORR R2,R2,#(1<<22) ; Bit 22 set to indicate empty
8250 BVS empty
8260 LDRB R3,CMOSbyte ; If in Immediate mode, then
8270 TST R3,#%001 ; trash can is always 'empty'
8280 BNE empty
8290 MOVS R0,R0
8300 BICNE R2,R2,#(1<<22) ; Bit 22 cleared because full
8310.empty STR R2,trashstat
8320 BL updatecan
8330 LDMFD R13!,{R0-R3,PC}
8340.trashbits EQUS "<"+trashvar$+">"
8350.poketrash EQUS bl$+"*"+bl$
8360 ALIGN
8370
8380.redocontents
8390
8400; Like checkcontents, but uses last scan for info rather than re-scanning
8410
8420 STMFD R13!,{R2,R10,R14}
8430 LDR R2,trashstat ; Get last scan
8440 MOV R10,#1 ; Flag icon update
8450 BL updatecan
8460 LDMFD R13!,{R2,R10,PC}
8470
8480.updatecan
8490
8500; On entry, R2 = Trashstat value
8510; R10 = 0 if want to create icon, <> 0 to update it
8520
8530 STMFD R13!,{R1,R14}
8540 TST R2,#(1<<22)
8550 MOVNE R1,#ASC"1" ; Empty flag (Philip Colmer)
8560 MOVEQ R1,#ASC"2" ; Full flag
8570 MOVS R10,R10 ; Is this the first time the
8580 BLEQ makeicon ; icon is to appear on the bar ?
8590 BLNE changeicon
8600 MOV R1,#0
8610 STRB R1,fsctrlflag ; No need for more updates
8620 LDMFD R13!,{R1,PC}
8630
8640.canexists
8650
8660; Must create trash directory if it doesn't exist
8670
8680 STMFD R13!,{R0,R1,R14}
8690 ADR R1,trashopenbuff
8700 BL readtrashdir ; Make sure Trash$Dir var exists
8710 MOV R0,#0
8720 STRB R0,poketrash
8730 ADR R1,trashbits
8740 MOV R0,#8
8750 SWI "XOS_File" ; *CDIR <Trash$Dir>. III-854
8760 LDMFD R13!,{R0,R1,PC}
8770
8780.newname EQUS "<"+trashvar$+">"
8790.nameending EQUS "."+STRING$(11,bl$)
8800 ALIGN
8810
8820.getcaniconinfo
8830
8840; On exit, R2 = Right-hand X coord of trash can icon on icon bar
8850
8860 STMFD R13!,{R1,R3,R14}
8870 MVN R2,#-(iconbartype%+1) ; Icon bar type
8880 LDR R3,iconhandle ; Trash can icon handle
8890 BL geticoninfo
8900 LDR R2,[R1,#16] ; Get icon right X coord
8910 LDMFD R13!,{R1,R3,PC}
8920
8930.geticoninfo
8940
8950; On entry, R0 = Window handle
8960; R2 = Icon handle
8970; On exit, R1 = Pointer to IconState info
8980
8990 ADR R1,(trashclosebuff+3) DIV 4*4 ; Recycle workspc
9000 STR R2,[R1] ; Store window handle
9010 STR R3,[R1,#4] ; Store icon handle
9020 SWI "XWimp_GetIconState" ; Get icon info. III-1213
9030 MOV PC,R14
9040
9050.moveintotrash
9060
9070; On entry, R1 = Pointer to Wimp_Poll block
9080
9090 STMFD R13!,{R0-R6,R9,R14}
9100 LDRB R5,CMOSbyte ; Get Immediate option
9110 AND R5,R5,#%001
9120 BL startglass ; Hourglass on
9130 ADD R3,R1,#44 ; Point to filename
9140 BL canexists ; Create Trash dir if needed
9150
9160; Because *Rename is extremely awkward about wildcards - won't allow
9170; them (ARRGGHH !) - have to copy the name (from the last '.' onwards)
9180
9190 LDR R4,[R3,#-44+12] ; Is it from Filer ?
9200 MOVS R4,R4
9210 BEQ itsfromFiler ; Yes, so endings the same
9220 LDR R0,sparktaskhand
9230 LDR R1,[R3,#-44+4] ; Is it Spark ?
9240 CMP R0,R1
9250 BNE canttrash ; No, so ignore
9260 ADR R0,savedleaf ; and copy leafname to the
9270 ADR R1,nameending+1 ; end of Trash$Dir
9280.copysafeleaf LDRB R2,[R0],#1
9290 STRB R2,[R1],#1
9300 MOVS R2,R2
9310 BNE copysafeleaf
9320 B retryaccess
9330.itsfromFiler MOV R0,R3
9340 MOV R2,#0 ; Don't poke yet
9350.lookingforend LDRB R1,[R0],#1
9360 CMP R1,#ASC"." ; Still traversing dirs ?
9370 ADREQ R2,nameending
9380 MOVS R2,R2
9390 STRNEB R1,[R2],#1 ; Copy text into dest name
9400 MOVS R1,R1
9410 BNE lookingforend ; Got terminator yet ?
9420
9430; Next bit added to V1.01 to make sure that *Rename ALWAYS works
9440; if the file is on the same disk (avoiding having to *Copy locked files)
9450
9460.retryaccess MOV R0,#24 ; *Access <file> WR. III-910
9470 MOV R1,R3 ; Point to original filename
9480 ADR R2,attributes ; Point to WR access string
9490 BL dofscontrol
9500 BGT canttrash
9510.retryrename STMFD R13!,{R3}
9520 MOV R1,R3
9530 MOVS R5,R5 ; Immediate enabled ?
9540 MOVEQ R0,#25 ; *RENAME reason code. III-911
9550 ADREQ R2,newname
9560 SWIEQ "XOS_FSControl" ; *Rename. III-911
9570 BEQ attemptnewname
9580 ADR R6,callwipe ; (Optionally) animate van and
9590 MOV R9,R1 ; *Wipe everything from Trash$Dir
9600 BL dovananimation
9610 B attemptnewname
9620.callwipe STMFD R13!,{R0-R3,R14}
9630 MOV R0,#27 ; *WIPE reason code. III-915
9640 MOV R1,R9
9650 MOV R3,#%010000011 ; ~QF~CR~V and delete original
9660 SWI "XOS_FSControl" ; *Wipe. III-915
9670 LDMFD R13!,{R0-R3,PC}
9680.attemptnewname LDMFD R13!,{R3}
9690 BVC acknowledge ; Good, so acknowledge it
9700
9710; To prevent the silly copy of Trash into itself (causes 77 levels
9720; to be created !), the error code for Bad RENAME is checked.
9730
9740 LDR R1,[R0] ; Get the error word
9750 LDR R2,badrename
9760 CMP R1,R2 ; = &108B0 (Bad RENAME) ?
9770 BEQ canttrash
9780
9790; The only (non-fatal) way a rename can fail is if the rename is
9800; attempted across disks/FSs or into itself (when it's a dir)....
9810
9820 LDR R2,baddisk
9830 CMP R1,R2 ; = &1089F (Not same disc) ?
9840 CMPNE R1,#&B0 ; = &B0 (Bad rename) ?
9850
9860; ...or if it is already present in Trash$Dir (Already exists error)
9870
9880 LDRNE R2,doublecan
9890 CMPNE R1,R2 ; = &108C4 (Already exists) ?
9900 BEQ dotrashcopy
9910
9920; If it gets here, then there's a disk fault
9930
9940 BL generateerror
9950 CMP R1,#1
9960 BEQ retryrename
9970 BGT canttrash
9980.dotrashcopy MOVS R5,R5 ; If Immediate then *Wipe failed
9990 BNE canttrash ; so don't do anything else
10000 MOV R0,#26 ; *COPY reason code. III-912
10010 MOV R1,R3
10020 ADR R2,newname
10030 BL dofscontrol ; Do the *COPY
10040 BGT canttrash
10050
10060; This code added for V1.01 - should have been in V1.00...sorry.
10070
10080.acknowledge MOV R0,#17 ; User message
10090 SUB R1,R3,#44 ; Go back to block start
10100 LDR R2,[R1,#8] ; Get unique reference number
10110 STR R2,[R1,#12] ; Store it in response field
10120 MOV R2,#4
10130 STR R2,[R1,#16] ; DataLoadAck
10140 LDR R2,[R1,#4] ; Get task handle involved
10150 SWI "XWimp_SendMessage" ; Acknowledge drag
10160 MOVS R4,R4
10170 BLNE delsparkfile ; Delete Spark file
10180.canttrash LDMFD R13!,{R0-R6,R9,PC} ; Return (FS flag may be set)
10190.fakereturn MOV PC,R14 ; Fake return for animation
10200.badrename EQUD &108B0 ; Bad RENAME error code
10210.baddisk EQUD &1089F ; Not same disc error code
10220.doublecan EQUD &108C4 ; Already exists error code
10230
10240; Note that PUBLIC read-write (/WR) has NOT been used because anyone
10250; on Econet could hack around with the files whilst they're in the trash!
10260
10270.attributes EQUS "WR"+bl$ ; *Access attributes
10280 ALIGN
10290
10300.checkerror
10310
10320; On entry, R0 = Points to an error block (if V set)
10330; On exit, ZC = LT if no error, EQ if OK clicked, GT if Cancel
10340
10350 STMFD R13!,{R1,R14}
10360 MOVVC R1,#0
10370 BLVS generateerror
10380 CMP R1,#1 ; Tacky, but it works !
10390 LDMFD R13!,{R1,PC}
10400
10410.generateerror
10420
10430; On entry, R0 = Points to an error block
10440; On exit, R1 = 1 if OK clicked, 2 if Cancel clicked
10450
10460 STMFD R13!,{R0,R2,R14}
10470 MOV R1,#%0000011 ; OK & Cancel, Highlight OK
10480 ADR R2,errorname
10490 SWI "XWimp_ReportError" ; III-1243
10500 MOV R0,#0 ; Wimp_ReportError does an
10510 STRB R0,glassstat ; Hourglass_Smash, so need to
10520 BL startglass ; start it up again
10530 LDMFD R13!,{R0,R2,PC}
10540.errorname EQUS prog$+bl$
10550 ALIGN
10560
10570.startglass
10580
10590; Switch on Hourglass (busy delay = 1 second), but only if it is off
10600
10610 STMFD R13!,{R0,R14}
10620 LDRB R0,glassstat
10630 MOVS R0,R0
10640 MOVEQ R0,#100 ; 1 second to start
10650 STREQB R0,glassstat
10660 SWIEQ "XHourglass_Start" ; IV-1393
10670 LDMFD R13!,{R0,PC}
10680
10690.stopglass
10700
10710; Switch off Hourglass, but only if it is on
10720
10730 STMFD R13!,{R0,R14}
10740 LDRB R0,glassstat
10750 MOVS R0,R0
10760 MOVNE R0,#0
10770 STRNEB R0,glassstat
10780 SWINE "XHourglass_Off" ; IV-1391
10790 LDMFD R13!,{R0,PC}
10800
10810.byebye
10820
10830; This routine is called when the module is *RMKilled or *RMReInited.
10840
10850 STMFD R13!,{R2,R14}
10860 LDR R2,workspace ; Free (any) stack space
10870 SUBS R2,R2,#stackspace% ; Point to RMA start
10880 BLPL releaseRMA
10890 LDRPL R2,windowspace ; Release window space
10900 BLPL releaseRMA
10910 LDRPL R2,spritearea ; Release sprite area
10920 BLPL releaseRMA
10930 BL wimpclosedown ; Shut down active task
10940 MOV R2,#0
10950 STR R2,workspace ; Clear workspace flag
10960 LDMFD R13!,{R2,PC}
10970
10980.readCMOS STMFD R13!,{R0-R2,R14}
10990 MOV R0,#161 ; Read CMOS RAM to get saved
11000 MOV R1,#battery% ; settings of menu options
11010 SWI "XOS_Byte" ; II-787
11020 STRB R2,CMOSbyte ; Save for later modification
11030 LDR R0,immediatestat ; Configure tick on Immediate
11040 MOV R1,#%001 ; Bit 0 first
11050 BL twiddlebit
11060 STR R0,immediatestat
11070 LDR R0,warningstat ; Configure tick on Warning
11080 BL twiddlebit
11090 STR R0,warningstat
11100 LDR R0,animationstat ; Configure tick on Animation
11110 BL twiddlebit
11120 STR R0,animationstat
11130 LDMFD R13!,{R0-R2,PC}
11140
11150.twiddlebit
11160
11170; On entry, R0 = Menu status word
11180; R1 = Bit mask of status
11190; R2 = Status byte
11200; On exit, R0 = New value of menu status word
11210; R1 = Shifted left by 1
11220
11230 STMFD R13!,{R2,R14}
11240 BIC R0,R0,#(1<<0) ; Clear flag bit (0) on menu
11250 ANDS R2,R2,R1
11260 ORRNE R0,R0,#(1<<0) ; Set flag bit if switched on
11270 MOV R1,R1,ASL #1 ; Next menu is 1 bit on in CMOS
11280 LDMFD R13!,{R2,PC}
11290
11300.togglebit
11310
11320; On entry, R0 = Bit position to be toggled
11330
11340 STMFD R13!,{R0-R2,R14}
11350 MOV R1,#1 ; Straightforward EOR (1<<R0)
11360 LDRB R2,CMOSbyte ; Flip bit R0 in CMOS RAM
11370 EOR R2,R2,R1,ASL R0
11380 MOV R0,#162
11390 MOV R1,#battery%
11400 SWI "XOS_Byte" ; Update CMOS RAM. II-788
11410 BL readCMOS ; Re-read 'cos menu option changed
11420 LDMFD R13!,{R0-R2,PC}
11430
11440.dealwithmenu
11450
11460; On entry, R1 = Pointer to Wimp_Poll block
11470
11480 STMFD R13!,{R0-R2,R6,R9,R10,R14}
11490 LDR R0,[R1] ; Get item number (from 0)
11500 MOVS R0,R0
11510 BEQ ignoremenu ; Item #1 = Info (do nothing)
11520 CMP R0,#5 ; Item #6 = Quit
11530 LDREQ R9,[R1,#4]
11540 BEQ leavenow
11550 CMP R0,#4 ; Item #5 = Empty Trash
11560 BEQ dothebinning
11570; It it gets here, then must be Items #2-4 (Immediate, Warning, Animation)
11580 SUB R0,R0,#1 ; Invert tick on appropriate
11590 BL togglebit ; menu (updating CMOS RAM too)
11600 MOVS R0,R0 ; Skip if not Immediate
11610 BNE ignoremenu
11620 MOV R10,#1 ; If Immediate item toggled then
11630 BL checkcontents ; might need to re-enable fat can
11640 LDRB R0,CMOSbyte ; If Immediate toggled on, then
11650 TST R0,#%001 ; must shut down Trash Can Window
11660 BLNE notrashwind
11670 B ignoremenu
11680; Must be Item #5, which is only enabled if there is Trash
11690.dothebinning ADR R6,cleantrashdir
11700 BL dovananimation ; Trundle van time !
11710.ignoremenu LDMFD R13!,{R0-R2,R6,R9,R10,PC}
11720
11730.trashthestuff
11740
11750; On entry, R6 = Address of routine to be used for trashing
11760
11770 MOV PC,R6 ; Not exactly tricky to code...
11780
11790.cleantrashdir STMFD R13!,{R0,R1,R14}
11800 BL startglass ; Hourglass on
11810 MOV R0,#27 ; *WIPE reason code. III-915
11820 ADR R1,trashbits
11830 BL dofscontrol
11840 LDMFD R13!,{R0,R1,PC}
11850
11860.dofscontrol
11870
11880; On entry, R0 = OS_FSControl reason code
11890; R1 = Pointer to source name
11900; R2 = Pointer to dest name (not used with *WIPE)
11910
11920 STMFD R13!,{R3,R14}
11930 MOV R3,#ASC"."
11940 STRB R3,poketrash
11950.retrycopywipe STMFD R13!,{R0-R2}
11960 MOV R3,#%010000011 ; ~QF~CR~V and delete original
11970 SWI "XOS_FSControl"
11980 BL checkerror ; Keep trying until no error
11990 LDMFD R13!,{R0-R2} ; or Cancel clicked on
12000 BEQ retrycopywipe
12010 LDMFD R13!,{R3,PC} ; Return (FS flag will be set)
12020
12030.checkfordrag
12040; On entry, R1 = Pointer to Wimp_Poll block (used for workspace)
12050 STMFD R13!,{R0-R5,R14}
12060 SWI "XWimp_GetPointerInfo"
12070 LDR R2,[R1,#12] ; Get window handle
12080 LDR R3,[R1,#16] ; Get icon handle
12090 LDR R0,[R1,#8] ; Must have one of the buttons
12100 TST R0,#%101 ; down to start a drag
12110 MOVEQ R4,#0
12120 STREQ R4,sparkwindhand; If not, we don't know Spark's
12130 BEQ checkformenu ; window handle
12131 MOV R5,#1 ; Button down, away from can
12140 LDR R4,sparkwindhand; Skip if we already know
12150 MOVS R4,R4 ; Spark's window handle
12160 BNE couldbeoverme
12170 MOVS R3,R3 ; Only looking for an icon,
12180 BMI couldbeoverme ; not part of a window
12190 MOVS R4,R2 ; Make sure not background or
12200 BMI couldbeoverme ; icon bar
12210 LDR R1,windowspace
12220 MOV R0,#20
12230 STR R0,[R1] ; Block size
12240 MOV R0,#0
12250 STR R0,[R1,#12] ; my_ref = 0
12260 MOV R0,#19
12270 SWI "XWimp_SendMessage" ; Ask for owner handle
12280 LDR R0,sparktaskhand
12290 CMP R0,R2 ; Was it a Spark icon ?
12300 BNE notsparkdrag
12310 STR R4,[R1] ; Need to get more
12320 SWI "XWimp_GetWindowInfo" ; details. III-1210
12330 LDR R0,[R1,#28+4] ; Get window flags
12340 MOV R0,R0,LSR #24 ; Get icon control flags
12350 BIC R0,R0,#(%11<<7) ; Ignore bit sel/horiz scroll
12360 CMP R0,#%111111 ; Are all enabled ?
12370 BNE notsparkdrag
12380 LDR R0,[R1,#56+4]
12390 TST R0,#(1<<8) ; Is title info indirect ?
12400 BEQ notsparkdrag
12410 STR R4,sparkwindhand; Save window handle
12420 ADR R0,sparkrootcomm
12430 MOV R2,#LEN(sparkdel$)
12440 ADD R3,R1,#20
12450.stillcommmove LDRB R4,[R0],#1 ; Copy start of Spark command
12460 STRB R4,[R3],#1 ; into workspace area
12470 SUBS R2,R2,#1
12480 BNE stillcommmove
12490 LDR R0,sparktaskhand; Source task
12500 LDR R4,[R1,#72+8+4] ; Size of buffer
12510 LDR R1,[R1,#72+4] ; Pointer to window title
12520 LDR R2,taskhandle ; Destination task
12530 SWI "XWimp_TransferBlock" ; III-1283
12540
12550; Although we 'think' we know the length of the window title, it is
12560; only the buffer size - must find the terminating zero instead
12570
12580.findpathzero LDRB R0,[R3]
12590 MOVS R0,R0
12600 ADDNE R3,R3,#1
12610 BNE findpathzero
12620 STR R3,putleafhere ; That's where the leaf goes
12630 B notsparkdrag
12640.couldbeoverme CMN R2,#2 ; Window = -2 (icon bar) ?
12650 LDREQ R1,iconhandle
12660 CMPEQ R1,R3 ; Icon = Trash Can ?
12670 BNE notsparkdrag
12680
12690; If it gets here, then a button is down and the pointer is over the
12700; Trash Can icon.
12710
12720 LDRB R0,CMOSbyte ; Immediate and Warning enabled ?
12730 AND R0,R0,#%11
12740 CMP R0,#%11
12750 BNE notsparkdrag
12760
12770; However, 'dragstate' must have been set to 1 (away from can,
12780; button down) rather than 0 (button up) or 2 (over can, button down)
12790; prior to this if we want to turn the border red.
12800
12801 MOV R5,#2 ; Over can, button down
12810 LDRB R0,dragstate
12820 CMP R0,#1
12830 BLEQ turnborderred ; OK, so warn user that he's
12840 B dontchange ; about to destroy files
12850
12860; At this point, R0 = Button state
12870; R1 = GetPointerInfo block, R2/R3 = window/icon handles
12880; Must see if pointer is over 'Empty Trash' (enabled) menu option
12890
12900.checkformenu
12910]
12920IF debug% THEN
12930[OPT A%
12940 BL showhandles ; Display handles in top left
12950]
12960ENDIF
12970[OPT A%
12971 MOV R5,#0 ; Button up, away from can
12980 CMP R3,#5*3-2 ; On fifth item (Empty Trash) ?
12990 BNE notsparkdrag
13000 LDRB R0,CMOSbyte ; Warning enabled ?
13010 AND R0,R0,#%10
13020 CMP R0,#%10
13030 BNE notsparkdrag
13040 BL getmenuiconinfo ; Yes, so get menu item text
13050 MOV R4,#3
13060.scanformiss LDR R2,[R0],#4 ; Compare "Empty Trash" with
13070 LDR R3,[R1],#4 ; menu item text to see if
13080 CMP R2,R3 ; it's my menu (only easy way !)
13090 BNE notsparkdrag
13100 SUBS R4,R4,#1
13110 BNE scanformiss
13120 BL turnborderred ; Turn border red if on item
13130 B dontchange
13140.notsparkdrag BL checkforred ; Not over can, so remove red
13160.dontchange STRB R5,dragstate
13161 LDMFD R13!,{R0-R5,PC}
13170.putleafhere EQUD 0
13180.sparkrootcomm EQUS sparkdel$
13190 ALIGN
13200]
13210IF debug% THEN
13220[OPT A%
13230; Start of debugging code
13240
13250.showhandles
13260
13270; On entry, R2/R3 = Window/icon handles (from GetPointerInfo)
13280
13290 STMFD R13!,{R0,R14}
13300 SWI XOS_WriteI+4 ; VDU 4 for fast text
13310 SWI XOS_WriteI+30 ; VDU 30 to keep in top left
13320 MOV R0,R2 ; Display window handle
13330 BL outhex
13340 SWI "XOS_NewLine" ; Next line. I-166
13350 MOV R0,R3 ; Display icon handle
13360 BL outhex
13370 SWI XOS_WriteI+5 ; Back to slow text again
13380 LDMFD R13!,{R0,PC}
13390
13400.outhex
13410
13420; On entry, R0 = Value to printed as 8 hex digits
13430
13440 STMFD R13!,{R0-R2,R14}
13450 ADR R1,hexbuffer ; Convert R0 into 8 zero-padded
13460 MOV R2,#9 ; hex digits...
13470 SWI "XOS_ConvertHex8" ; II-601
13480 MOV R1,#8 ; ...and print them out
13490 SWI "XOS_WriteN" ; I-189
13500 LDMFD R13!,{R0-R2,PC}
13510.hexbuffer EQUS STRING$(12,bl$)
13520
13530; End of debugging code
13540]
13550ENDIF
13560[OPT A%
13570.checkforred STMFD R13!,{R0,R2,R14}
13580 LDRB R0,modifiedbord ; If border is red,
13590 MOVS R0,R0
13600 LDRNE R0,curbordercol ; then restore to its previous
13610 MOVNE R2,#0 ; colour
13620 BLNE restoreborder
13630 LDMFD R13!,{R0,R2,PC}
13640
13650.turnborderred STMFD R13!,{R0,R1,R14}
13660 LDRB R0,modifiedbord ; Skip if already red
13670 MOVS R0,R0
13680 BNE alreadycooked
13690 ADR R1,wimppalette ; Simply read all 16 colours
13700 SWI "XWimp_ReadPalette" ; and save them. III-1251
13710 LDR R0,[R1,#64] ; Read and save border colour
13720 STR R0,curbordercol
13730 MOV R0,#&00F000 ; Red in RGB values
13740 MOV R2,#1 ; Flag as modified
13750 BL restoreborder ; Change border colour to red
13760.alreadycooked LDMFD R13!,{R0,R1,PC}
13770.curbordercol EQUD 0
13780.wimppalette EQUS STRING$(80,bl$)
13790.modifiedbord EQUB 0
13800 ALIGN
13810
13820.restoreborder
13830
13840; On entry, R0 = RGB value for border
13850; R2 = Modified flag
13860
13870 STMFD R13!,{R1,R14}
13880 STRB R2,modifiedbord
13890 ADR R1,wimppalette
13900 STR R0,[R1,#64] ; Store border colour
13910 BL videosync ; Smooth out change
13920 SWI "XWimp_SetPalette" ; Mod border colour. III-1250
13930 LDMFD R13!,{R1,PC}
13940
13950.copyhelpmess
13960
13970; On entry, R0 = Source address of message
13980; R2 = Dest address of message
13990; On exit, R2 = Updated dest address
14000
14010 STMFD R13!,{R0,R1,R14}
14020.suckuphelp LDRB R1,[R0],#1 ; Copy help text into
14030 MOVS R1,R1
14040 STRNEB R1,[R2],#1 ; message packet
14050 BNE suckuphelp
14060 LDMFD R13!,{R0,R1,PC}
14070
14080.askedforhelp
14090
14100; On entry, R1 = Pointer to Wimp_Poll block
14110; R4 = 0 if icon, <> 0 if Info Window
14120
14130 STMFD R13!,{R0-R3,R14}
14140 ADD R2,R1,#20 ; Where the help text is to go
14150 MOVS R4,R4 ; Is it the icon or Info window ?
14160 BEQ itsiconhelp
14170 ADR R0,helpmessinfo ; Info Window help
14180 BL copyhelpmess
14190 B finishmessnow
14200.itsiconhelp ADR R0,helpmessicon ; First help line is constant
14210 BL copyhelpmess
14220 LDRB R3,CMOSbyte ; Now decide on Immediate text
14230 TST R3,#%001 ; or Trash$Dir info
14240 ADRNE R0,helpimmed
14250 ADREQ R0,helpstore
14260 BL copyhelpmess
14270 TST R3,#%010 ; Add Warning text if enabled
14280 ADRNE R0,helpwarn
14290 BLNE copyhelpmess
14300 TST R3,#%100 ; Add Animation text if enabled
14310 ADRNE R0,helpanim
14320 BLNE copyhelpmess
14330.finishmessnow MOV R0,#0 ; Null terminator needed
14340 STRB R0,[R2,#-2]
14350 ADD R0,R2,#2 ; Compute word-rounded length of
14360 BIC R0,R0,#%11 ; message block
14370 SUB R0,R0,R1
14380 STR R0,[R1] ; Save length in block
14390 LDR R2,[R1,#4] ; Task handle to reply to
14400 LDR R0,[R1,#8] ; Copy reference number
14410 STR R0,[R1,#12]
14420 MOV R0,#&500
14430 ADD R0,R0,#3 ; !Help reply ID = &503
14440 STR R0,[R1,#16]
14450 MOV R0,#17
14460 SWI "XWimp_SendMessage"
14470 LDMFD R13!,{R0-R3,PC}
14480.helpmessinfo EQUS "This is the Info Window.|MIt shows the name and purpose of this application as well as the author, "
14490 EQUS "version number and date developed. It employs 'auto-stamping' to "
14500 EQUS "synchronise "+prog$+" module and Info Window versions and dates.|M"+bl$
14510 ALIGN
14520.helpmessicon EQUS "This is the "+prog$+" icon. Drag files onto it to "+bl$
14530 ALIGN
14540.helpimmed EQUS "delete them immediately.|MMENU: Toggles options.|M"+bl$
14550 ALIGN
14560.helpstore EQUS "put them in the "+prog$+".|MMENU: Toggles options/empties trash. SELECT or ADJUST: View trash.|M"+bl$
14570 ALIGN
14580.helpwarn EQUS "A red border warning is shown before deletion.|M"+bl$
14590 ALIGN
14600.helpanim EQUS "A Trash Van will pick up the trash.|M"+bl$
14610 ALIGN
14620
14630.videosync STMFD R13!,{R0-R2,R14}
14640 MOV R0,#19 ; WAIT (watch out - annoyingly
14650 SWI "XOS_Byte" ; corrupts R1 and R2 !). I-298
14660 LDMFD R13!,{R0-R2,PC}
14670
14680.wimpspriteop
14690
14700; On entry, R0 = OS_SpriteOp reason code
14710; R2 = Pointer to sprite name (or filename)
14720; R3.. = Other OS_SpriteOp params
14730
14740 STMFD R13!,{R0-R2,R14}
14750
14760; Note to Acorn - I would DEARLY like to use Wimp_SpriteOp exclusively
14770; in this module, but it doesn't support any "write" operations !
14780
14790 ADD R0,R0,#&100 ; Pointing to special user area
14800 SWI "XWimp_SpriteOp"; III-1271
14810.leavespriteop LDMFD R13!,{R0-R2,PC}
14820
14830.spriteop
14840
14850; On entry, R0 = OS_SpriteOp reason code
14860; R2 = Pointer to sprite name (or filename)
14870; R3.. = Other OS_SpriteOp params
14880
14890 STMFD R13!,{R0-R2,R14}
14900 ADD R0,R0,#&100 ; Flag user area
14910 LDR R1,spritearea
14920 SWI "XOS_SpriteOp" ; I-393
14930 LDMFD R13!,{R0-R2,PC}
14940
14950.trundlevan
14960
14970; On entry, R0 = Pointer to sprite family name
14980; R1 = Start position
14990; R2 = Finish position
15000; R3 = OS units between each movement (can be -ve)
15010; R7/R8 = X/Y shift
15020
15030 STMFD R13!,{R0-R10,R14}
15040 STMFD R13!,{R0-R3}
15050 MOV R2,R0
15060 MOV R9,#ASC"1" ; Select first sprite
15070 STRB R9,[R2,#6]
15080 MOV R0,#40 ; Read sprite info
15090 BL wimpspriteop ; I-423
15100 BVS spritefailure ; Give up if no sprite
15110 MOV R5,#1 ; Bottom of van = 1 pixel above
15120 MOV R5,R5,ASL R8 ; screen bottom (scale it)
15130 SUBS R3,R3,#1 ; Width of sprite - 1
15140 BMI spritefailure ; Give up if width = 0
15150 MOV R7,R3,ASL R7 ; then shift it by the Xfactor
15160 SUBS R4,R4,#1 ; Height of sprite - 1
15170 BMI spritefailure ; Give up if height = 0
15180 MOV R8,R4,ASL R8 ; then shift it by the Yfactor
15190 LDMFD R13!,{R0-R3}
15200 BL saveundervan ; Initial temp sprite setup
15210 BVS vanhitfinish
15220
15230; The rest of this routine deals with moving the van (smoothly !) in
15240; a straight horizontal line between R1 and R2 (step R3). It flips
15250; between 3 different sprites every third video sync.
15260
15270.animationflip MOV R10,#3 ; Reset flip counter
15280 STRB R9,[R0,#6] ; Select sprite
15290.noanimflip BL videosync ; Smooth out animation
15300 ADR R4,tempoutsprite; Select saved rectangle
15310 MOV R6,#0 ; Overwrite screen
15320 BL plotsprite ; Restore underneath rectangle
15330 BVS vanhitfinish
15340 ADD R1,R1,R3 ; Move van xcoord
15350 MOVS R3,R3 ; Which way is the van going ?
15360 BPL lefttoright
15370 CMP R1,R2 ; If left, then stop when less
15380 BLT vanhitfinish
15390 B vanstillgoing
15400.lefttoright CMP R1,R2 ; If right, then stop when more
15410 BGT vanhitfinish
15420.vanstillgoing BL saveundervan ; Save underneath again
15430 BVS vanhitfinish
15440 MOV R4,R0
15450 MOV R6,#8 ; Overwrite but use mask
15460 BL plotsprite ; Plot van in new position
15470 BVS vanhitfinish
15480 SUBS R10,R10,#1
15490 BNE noanimflip ; Have 3 moves gone by ?
15500 ADD R9,R9,#1 ; Yes, so next sprite please
15510 CMP R9,#ASC"4"
15520 MOVEQ R9,#ASC"1"
15530 B animationflip
15540.spritefailure LDMFD R13!,{R0-R3}
15550.vanhitfinish LDMFD R13!,{R0-R10,PC}
15560
15570.saveundervan
15580
15590; On entry, R1 = Left X position of van
15600; R5 = Bottom Y position of van
15610; R7/R8 = Van sprite width/height (minus one unit)
15620
15630 STMFD R13!,{R0-R7,R14}
15640 ADR R2,tempoutsprite
15650 MOV R3,#0 ; No palette
15660 MOV R4,R1 ; Left side
15670 ADD R6,R4,R7 ; Right side (Left+Width)
15680 ADD R7,R5,R8 ; Top side (Bottom+Height)
15690 MOV R0,#16 ; Save rectangle to sprite
15700 BL spriteop ; I-405
15710 LDMFD R13!,{R0-R7,PC}
15720
15730.plotsprite
15740
15750; On entry, R1 = Left xcoord
15760; R4 = Pointer to sprite name
15770; R5 = Bottom ycoord
15780; R6 = Action code (0 = overwrite, 8 = ditto with mask)
15790
15800 STMFD R13!,{R0-R5,R9,R14}
15810 MOV R2,R4 ; Lots of register juggling !
15820 MOV R3,R1
15830 MOV R4,R5
15840 MOV R5,R6
15850 MOV R0,#34 ; Plot sprite. I-417
15860 MOV R9,R6
15870 BL choosesprcall
15880 LDMFD R13!,{R0-R5,R9,PC}
15890
15900.choosesprcall
15910
15920; On entry, R9 = 0 => Use OS_SpriteOp, <> 0 => Use Wimp_SpriteOp
15930
15940 STMFD R13!,{R14}
15950 MOVS R9,R9 ; Select routine depending on reg
15960 BEQ donormsprcall
15970 BL wimpspriteop
15980 B endthesprcall
15990.donormsprcall BL spriteop
16000.endthesprcall LDMFD R13!,{PC}
16010
16020.dovananimation
16030
16040; On entry, R6 = Address of routine to call for trashing
16050; On exit, V = Set if trashing failed
16060
16070 STMFD R13!,{R0-R8,R14}
16080 LDRB R0,CMOSbyte
16090 TST R0,#%100 ; Animation enabled ?
16100 BEQ noanimtoday
16110 ADR R0,inputblock
16120 ADR R1,outputblock
16130 SWI "XOS_ReadVduVariables" ; Get mode info. I-345
16140 LDR R0,[R1] ; Is it a 16-colour MODE ?
16150 CMP R0,#15
16160 BEQ itsa16col
16170.noanimtoday BL trashthestuff ; Not right mode, so delete now
16180 B endofseq
16190.itsa16col BL getcaniconinfo ; R2 = Right X coord of icon
16200 BL inituserarea ; *SNew the user sprite area
16210 LDR R7,[R1,#4] ; X shift needed
16220 LDR R8,[R1,#8] ; Y shift needed
16230 LDR R1,[R1,#12] ; Number of X pixels - 1
16240 MOV R1,R1,ASL R7 ; Start = far right
16250 BIC R1,R1,#%1111 ; Make sure a multiple of 16
16260 MOV R0,#4
16270 ADD R2,R2,R0,ASL R7 ; Finish = 4 pixels to can right
16280 BIC R2,R2,#%1111 ; Also a multiple of 16
16290 ADR R0,vanleftname ; Van is pointing to left
16300 MVN R3,#15 ; Go left 16 OS units at time
16310 BL trundlevan
16320 BL trashthestuff ; Delete (rename) the stuff
16330 BVS endofseq
16340 MOV R0,R1 ; New Start = Old Finish
16350 MOV R1,R2 ; and vice versa
16360 MOV R2,R0
16370 ADR R0,vanrightname ; Van is pointing to right
16380 RSB R3,R3,#0 ; Flip travel direction
16390 BL trundlevan
16400.endofseq LDMFD R13!,{R0-R8,PC}
16410.inputblock EQUD 3 ; NColour
16420 EQUD 4 ; XEigFactor
16430 EQUD 5 ; YEigFactor
16440 EQUD 11 ; XWindLimit
16450 EQUD -1
16460.outputblock EQUS STRING$(16,bl$)
16470.tempoutsprite EQUS "tempvan"+bl$
16480
16490.scantrashspr STMFD R13!,{R1,R2,R14}
16500 ADR R1,iconspritename
16510 ADR R2,trashiconname
16520 BL iconsprites ; Load in trash can sprites
16530 LDMFD R13!,{R1,R2,PC}
16540
16550.iconsprites
16560
16570; On entry, R1 = Filename to load if R2 sprite not present
16580; R2 = Sprite name to check for existence
16590
16600 STMFD R13!,{R0-R6,R14}
16610 MOV R0,#40 ; Read sprite info reason code
16620 BL wimpspriteop ; Does sprite exist ? I-423
16630 MOVVS R0,#11 ; Merge sprite file reason code
16640 MOVVS R2,R1
16650 BLVS wimpspriteop ; I-400
16660 ADRVS R0,wotnoicons
16670 SWIVS "OS_GenerateError"
16680 LDMFD R13!,{R0-R6,PC}
16690.wotnoicons EQUD 0
16700 EQUS prog$+" sprites could not be loaded"+bl$
16710 ALIGN
16720
16730.scanvanspr STMFD R13!,{R1,R2,R14}
16740 ADR R2,vanleftname
16750 MOV R1,#ASC"3"
16760 STRB R1,[R2,#6]
16770 ADR R1,loadthevan
16780 BL iconsprites ; Load in trash van sprites
16790 LDMFD R13!,{R1,R2,PC}
16800.trashiconname EQUS "!trash2"+bl$
16810.iconspritename EQUS "<TrashWork$Dir>.!Sprites"+bl$
16820 ALIGN
16830.vanleftname EQUS "vanlft1"+bl$
16840.vanrightname EQUS "vanrgt1"+bl$
16850.loadthevan EQUS "<TrashWork$Dir>.VanSprites"+bl$
16860 ALIGN
16870
16880.loadtemplate
16890
16900; Load in Info window template. I'm not happy that the LoadTemplate docs
16910; in the new PRMs fail to refer you to OpenTemplate (which MUST be called
16920; first to tell the WIMP which template file you're dealing with). Yes,
16930; you can find the blurb on III-1153, but I would've liked a clue - I
16940; kept getting 'Channel' errors until I realised what was going on !
16950
16960 STMFD R13!,{R0-R6,R14}
16970 LDR R1,templatehandle ; Already got template ?
16980 MOVS R1,R1
16990 BNE havetemplate
17000 ADR R1,tempfilename ; New template file
17010 SWI "XWimp_OpenTemplate" ; III-1236
17020 ADRVS R0,wotnotempfile ; Certainly can't go on
17030 SWIVS "OS_GenerateError" ; if no template file
17040 LDR R1,workspace
17050 SUB R1,R1,#stackspace% ; Point to start of RMA
17060 ADD R2,R1,#&300 ; Indirected data goes here
17070 ADD R3,R2,#&100 ; End of indirected data
17080 MVN R4,#0 ; -1 => no fonts involved
17090 ADR R5,templatename ; Point to template name
17100 MOV R6,#0 ; First call (actually want Info window)
17110 SWI "XWimp_LoadTemplate" ; III-1238
17120 MOVS R6,R6 ; I want my Info window !
17130 ADREQ R0,wotnoinfowind ; (R6=0 if not found)
17140 SWIEQ "OS_GenerateError"
17150; Wimp_LoadTemplate has left R1 pointing to the Info window template
17160; so it's best to store the handle and then create the window
17170 STR R1,templatehandle
17180 ADR R5,specialyear
17190 ADR R6,autoyear
17200 BL autostamptemp ; Add year
17210 ADR R5,specialstamp
17220 ADR R6,autodate
17230 BL autostamptemp ; Add version/date
17240 SWI "XWimp_CloseTemplate" ; III-1237 (ignore error)
17250.havetemplate SWI "XWimp_CreateWindow" ; III-1174 (ignore error)
17260 STR R0,submenupoke ; Info sub-menu item
17270 LDMFD R13!,{R0-R6,PC}
17280.templatename EQUS "Info"+STRING$(8,bl$)
17290.templatehandle EQUD 0
17300.tempfilename EQUS "<TrashWork$Dir>.Templates"+bl$
17310 ALIGN
17320.wotnotempfile EQUD 0
17330 EQUS "No "+prog$+" template file"+bl$
17340 ALIGN
17350.wotnoinfowind EQUD 0
17360 EQUS "No Info window in template file"+bl$
17370.specialyear EQUS "YYYY"
17380.autoyear EQUS RIGHT$(date$,4)+cr$
17390.specialstamp EQUS "A.BB"
17400.autodate EQUS resdate$+cr$
17410 ALIGN
17420
17430.autostamptemp
17440
17450; On entry, R1 = Template data start
17460; R3 = Template data end
17470; R5 = Pointer to special search string (4 bytes)
17480; R6 = Pointer to replacement string (CR-termed)
17490
17500 STMFD R13!,{R0-R4,R14}
17510.scanallfour MOV R2,#3 ; Search string = 4 bytes
17520.stillnostamp LDRB R4,[R1,R2]
17530 LDRB R0,[R5,R2]
17540 CMP R4,R0
17550 BNE nosubmatch ; Next byte if no match
17560 SUBS R2,R2,#1 ; Keep scanning until all four
17570 BPL stillnostamp ; found
17580 B exactdate
17590.nosubmatch ADD R1,R1,#1 ; Next byte (leave if no more)
17600 CMP R1,R3
17610 BNE scanallfour
17620 B nochangetodate
17630.exactdate MOV R0,R6 ; Copy replacement string on
17640.doautostamp LDRB R2,[R0],#1 ; top of search result addr
17650 STRB R2,[R1],#1 ; up until a CR (indirected data
17660 CMP R2,#13 ; ends in a CR, not 0).
17670 BNE doautostamp
17680 B scanallfour
17690.nochangetodate LDMFD R13!,{R0-R4,PC}
17700
17710.getmenuiconinfo
17720
17730; On entry, R2 = Window handle
17740; R3 = Icon handle
17750; On exit, R0 = Pointer to text string
17760; R1 = Pointer to 'Empty Trash' menu string
17770 STMFD R13!,{R2,R3,R14}
17780 BL geticoninfo
17790 ADD R0,R1,#28 ; Pointer to menu text
17800 ADR R1,trashstat+4
17810 LDMFD R13!,{R2,R3,PC}
17820
17830.makenewmenu
17840
17850; On entry, R1 = Pointer to Wimp_Poll block
17860
17870 STMFD R13!,{R2,R14}
17880 LDR R2,[R1] ; Get X returned from Wimp_Poll
17890 SUB R2,R2,#64 ; Subtract 64 for easy access
17900 STR R2,newmenux ; Save X coord
17910 BL makemenu
17920 LDMFD R13!,{R2,PC}
17930
17940.makeoldmenu STMFD R13!,{R2,R14}
17950 LDR R2,newmenux ; Retrieve X coord
17960 BL makemenu
17970 LDMFD R13!,{R2,PC}
17980
17990.makemenu
18000
18010; On entry, R2 = X coord of menu
18020; Must display a menu using Wimp_CreateMenu.
18030
18040 STMFD R13!,{R1,R3,R14}
18050 MOV R3,#228 ; Menu Y = 228 if on icon bar
18060 ADD R3,R3,#44*3 ; + 3 items worth for new bits
18070 ADR R1,multiquitaddr
18080 STR R1,multiquitpoke
18090 ADR R1,menublock
18100 SWI "XWimp_CreateMenu" ; III-1226
18110 LDMFD R13!,{R1,R3,PC}
18120.newmenux EQUD 0 ; Save menu X coord here
18130
18140.menublock
18150; Menu structure first...
18160 EQUS prog$+STRING$(12-LEN(prog$),bl$) ; Menu title
18170 EQUB 7 ; Foreground = 7 (normally black)
18180 EQUB 2 ; Background = 2 (normally grey)
18190 EQUB 7 ; Work fore = 7 (normally black)
18200 EQUB 0 ; Work back = 0 (normally white)
18210 EQUD 188 ; Total width of menu items
18220 EQUD 44 ; Total height of menu items
18230 EQUD 0 ; Line spacing between items
18240; ...then Menu item #1
18250 EQUD 0 ; Nothing special
18260.submenupoke EQUD 0 ; Sub-menu addr poked in here
18270 EQUD (7<<24) OR 1 ; Item has text and is black
18280 EQUS "Info "+bl$
18290; ...then Menu item #2
18300.immediatestat EQUD 0 ; Nothing special
18310 EQUD -1 ; No sub-menu
18320 EQUD (7<<24) OR 1 ; Item has text and is black
18330 EQUS "Immediate "+bl$ ; Menu item
18340; ...then Menu item #3
18350.warningstat EQUD 0 ; Nothing special
18360 EQUD -1 ; No sub-menu
18370 EQUD (7<<24) OR 1 ; Item has text and is black
18380 EQUS "Warning "+bl$ ; Menu item
18390; ...then Menu item #4
18400.animationstat EQUD 0 ; Nothing special
18410 EQUD -1 ; No sub-menu
18420 EQUD (7<<24) OR 1 ; Item has text and is black
18430 EQUS "Animation "+bl$ ; Menu item
18440; ...then Menu item #5
18450 EQUD 0 ; Nothing special
18460 EQUD -1 ; No sub-menu
18470; This word has to have bit 22 changed depending on Trash contents
18480; Bit 22 refers to whether the item is shaded (unselectable) or not
18490.trashstat EQUD (7<<24) OR 1 ; Item has text and is black
18500 EQUS "Empty Trash"+bl$ ; Menu item
18510; ...and finally Menu item #6
18520 EQUD &80 ; Last menu item
18530.multiquitpoke EQUD 0 ; Quit sub-menu addr poked in here
18540 EQUD (7<<24) OR 1 ; Item has text and is black
18550 EQUS "Quit "+bl$ ; Menu item
18560; Now for the Quit option sub-menu
18570.multiquitaddr EQUS "Quit"+STRING$(8,bl$) ; Menu title
18580 EQUB 7 ; Foreground = 7 (normally black)
18590 EQUB 2 ; Background = 2 (normally grey)
18600 EQUB 7 ; Work fore = 7 (normally black)
18610 EQUB 0 ; Work back = 0 (normally white)
18620 EQUD 156 ; Total width of menu items
18630 EQUD 44 ; Total height of menu items
18640 EQUD 0 ; Line spacing between items
18650; Menu item #1
18660 EQUD 0 ; Nothing special
18670 EQUD -1 ; No sub-menu
18680 EQUD (7<<24) OR 1 ; Item has text and is black
18690 EQUS "Temporary "+bl$
18700; Menu item #2
18710 EQUD &80 ; Last menu item
18720 EQUD -1 ; No sub-menu
18730 EQUD (7<<24) OR 1 ; Item has text and is black
18740 EQUS "Permanent "+bl$
18750]NEXT
18760
18770REM Save as a module !RunImage
18780F$="$.!Trash.!RunImage"
18790SYS "OS_File",&A,F$,&FFA,,org,P%
18800END
18810
18820REM OK, I could change @%, but can YOU understand the various bits of @% ?
18830REM Why on earth didn't Roger put new FIELD,PLACES etc. keywords in ?
18840DEFFNfraction(V%)=STR$(V% DIV 100)+"."+RIGHT$("0"+STR$(V% MOD 100),2)
� >$.!Trash.TrashSrc
>� RISC OS Trash Can Module V1.40 (C) Richard K. Lloyd 1990
(
2G� This source code is released into the Public Domain for anyone to
<?� use, although some credit in your source might be nice...
F
P� Special thanks to:
Z;� - Philip Colmer (PColmer@uk.co.acorn) for suggestions
d5� - Rabin Ezra (rabin@uk.ac.qmc.cs) for bug fixes
nH� - David Pilling (mcbmsdp@uk.ac.mcc.cms) for a beta-test Spark 2.00
xB� - Gary Bartlett () for the Trash Van inspiration and sprites
�J� - Me (rkl@uk.ac.liv.cs.and) for filling a gaping hole in the Desktop
�
�?� Volume/page references are for the RISC OS Issue 1 (1989)
�.� 4-volume Programmer's Reference Manuals.
�
�*� Version 1.40 Released September 1990
�5� - Context-sensitive !Help information provided.
�A� - "Persistent" menu if right button pressed on a menu item.
�I� - New sprites with a Spark-like "flash" - shown if Spark installed.
�;� - Now "Spark-aware" regardless of installation order.
�K� - Incorrect border flash when clicking instead of dragging now fixed.
�
�%� Version 1.30 Released July 1990
I� - Configuration of new menu options (see below) stored in CMOS RAM.
K� - 'Immediate' menu option to erase files straight away on a trashing.
J� - 'Warning' menu option to turn the border red during dangerous ops.
"H� - 'Animation' menu option to show an icon bar Van during deletion.
,H� - New VanSprites file (and code to handle it) for above animation.
6K� - Fixed Info template workspace fault (force reload after Temp Quit).
@J� - Auto-time/datestamp updating of Info window without using !Formed.
JD� - Added, ahem, a "debug%" flag for window/icon handle display.
TG� - 'Immediate' mode now accidentally simulates the behaviour of an
^J� Atari ST trash can ! In other words, no fat icon, no Trash Window,
hK� no retention of trashed files in Trash$Dir. Pretty rubbish (!) eh ?
r
|(� Version 1.20 Released January 1990
�J� - Report errors if any occur during the trashing/emptying processes.
�C� - Switch on hourglass if trashing takes longer than 1 second.
�E� - Supports file trashing from inside archives using Spark 2.xx.
�J� - Displays an error if *Desktop_TrashCan issued outside the Desktop.
�
�@� Version 1.11 Released November 1989 (2 days after V1.10 !)
�4� - Fixed *fatal* bug with V1.10 Info menu item.
�,� - Slightly re-coded Quit menu parsing.
�9� - Adjusted menu widths and heights (Philip Colmer).
�:� - Allowed Info window to be dragged (Philip Colmer).
�
�)� Version 1.10 Released November 1989
�1� - Enhancements by Philip Colmer from 1.02a:
K� - Third sprite added to overcome trash can 'love-handles' in Filer.
H� - Correction of icon bar parameter block (wildly wrong in 1.02).
>� - Hard-coded Info window replaces cheap sub-menu Info.
&+� - Enhancements by RKL on top of this:
0E� - Uses Templates for Info window (boy, do I hate !FormEd...).
:3� - New Temporary/Permanent Quit menu option.
D?� - Claims RMA during module life for internal workspace.
NI� - Set TrashWork$Dir to <Obey$Dir> in !Run (template/sprites dir).
XA� - Performs internal *IconSprites call (Wimp_SpriteOp 11).
b
lC� Version 1.02a - not released (Modifications by Philip Colmer)
v
�)� Version 1.02 Released November 1989
�C� - Had to redefine !Trash sprite because of Wimp_SetIconState.
�1� - Bug fixes (including code) by Rabin Ezra:
�0� - Extended Trash$Dir buffer to 64 chars.
�:� - Checked for Trash$Dir expansion buffer overflow.
�2� - Zero-terminated the Trash$Dir expansion.
�E� - Improvement suggestions (with coding hints) by Philip Colmer:
�8� - Moved Trash Can icon to left side of icon bar.
�3� - Improved filing system activity trapping.
�5� - Stopped annoying icon bar "icon shuffling".
�
�%� Version 1.01 Released July 1989
�#� - Fixed rename inconsistency.
0� - Added Wimp_Poll message acknowledgement.
B� - Extended maximum length of expanded Trash$Dir to 48 chars.
2� - Set Trash$Dir to <Obey$Dir>.Trash in !Run.
E� - Posted with Acorn's "official" uuencode to avoid IBM munging.
*
4%� Version 1.00 Released July 1989
>H� - Mac-style trash can with Mac-style icons (ResEdit was useful !).
HF� - Survives anything except hard reset, module kill or power off.
R
\C� Check out the Indigo Girls' eponymously-titled album (on CD):
fL� great acoustic guitar harmonies - reached US #22 (sadly nowhere in UK)
pL� RKL's Best Album Of 1989: Diesel Park West's "Shakespeare Alabama" CD.
z'� RKL's Best Albums Of 1990 so far:
�>� All those Beach Boys 2-for-1 CD reissues - great stuff !
�
�*� org &2000:� Plenty of assembly space
�
�� Application constants
�
�3prog$="Trash Can":� English text name of module
�9ver$="1.40":� Version number of module in X.YY format
�H� Change next line to date$=MID$(TIME$,5,11) to get the current date
�8date$="10 Sep 1990":� Current date as a fixed string
�4resdate$=�date$,2)+"-"+�date$,4,3)+"-"+�date$,2)
�Dresdate$=ver$+" ("+resdate$+")":� Version/date for Info Template
�7command$="Desktop_TrashCan":� * command implemented
<trashvar$="Trash$Dir":� Trash can environmental variable
Cwimp$="Wimp$Scrap":� Wimp temporary file environmental variable
Kmaxpathlen%=64:� Maximum length of expanded Trash$Dir (inc. terminator)
$Jiconbartype%=-2:� -1 = Utility (RHS of bar), -2 = Service (LHS of bar)
.>windman%=200:� Expect at LEAST V2.00 of the Window Manager
8Gstackspace%=&800:� 2K for internal RMA stack and template workspace
BFwindowspace%=&800:� 2K for Wimp_GetWindowInfo / Wimp_TransferBlock
L1spritespace%=3*1024:� 3K for sprite user area
VJsparkdel$="!spark -d ":� Spark command to delete a file inside archive
`:battery%=38:� CMOS RAM location used to store settings
j>debug%=�:� So-called debugging - prints window/icon handle
t
~0� Time for some constants to help the reader
�
�2bl$=�(0):� NULL char used to terminate strings
�cr$=�(13):� Plain CR
�4UpCallV=&1D:� Warning vector for FS change check
�GXOS_WriteI=&20100:� X SWI form of OS_WriteI (used for VDU 7). I-199
�
�<Service_Reset =&27:� End of machine reset signalled
�FService_StartWimp =&49:� Request by Desktop to start WIMP modules
�DService_StartedWimp=&4A:� Desktop indicates all tasks now active
�
�� A%=0 � 2 � 2
�
P%=org
[OPT A%
E; Note that the module header must contain ADDRESS �SETS from the
I; start of the module, hence a subtraction of org is required. II-628
(
2F EQUD appstart-org ; Application start addr
<C EQUD init-org ; Initialisation addr
FA EQUD byebye-org ; Finalisation addr
PI EQUD servicecall-org ; Service call handler addr
ZH EQUD titlestr-org ; Module title string addr
d@ EQUD helpstr-org ; Help string addr
nG EQUD keywords-org ; Command/help table addr
x@ EQUD 0 ; No extra SWIs...
�B EQUD 0 ; What do you want ?
�7 EQUD 0 ; Blood ?
�A EQUD 0 ; Well hard luck...
�
�I; Title string to be used by *Modules and when *RMKilling etc. II-635
�I; Due to the way *Help works in RISC OS, avoid calling the module the
�I; same name as one of its * commands (I've been guilty of this ...!).
�
�*.titlestr EQUS "TrashCan"+bl$
� ALIGN
�
�9; Help string to be used in *Help Modules etc. II-635
�B; Note the tab character as recommended by Acorn. A second tab
G; character will be needed if prog$ is < 8 characters (unlikely !).
;.helpstr EQUS prog$+�(9)+ver$+" ("+date$+")"+bl$
" ALIGN
,
6B; Keyword lookup table for *Help and command execution. II-636
@G; Any addresses should, as usual, be offsets from the module start.
JF; Note- Modules that multi-task under the Wimp MUST have a startup
TF; * command because of the way Start_WimpTask is called when
^(; the Desktop first starts up.
h
r
.keywords
|<.startupname EQUS command$+bl$ ; * command name
�C ALIGN ; MUST include an ALIGN
�E EQUD startupcomm-org ; TrashCan exec addr �SET
�@ EQUB 0 ; Minimum params = 0
�D EQUB %00000000 ; No OS_GSTrans peformed
�@ EQUB 0 ; Maximum params = 0
�L EQUB %00000000 ; No *Conf or special *Help code
�I EQUD noparams-org ; Special params message �SET
�F EQUD startuphelp-org ; * command help text �SET
�@ EQUD 0 ; No more * commands
�
�M; If any parameters supplied, then complain. In actual fact, this message
�J; is displayed if params<min or params>max (just that min=max=0 here).
�
4.noparams EQUS "Syntax: *"+command$+bl$
ALIGN
&B; *Help text goes here. Avoid �(13) or �(10) unless absolutely
0E; necessary (usually to split the *Syntax message from the rest),
:A; because this text is OS_PrettyPrinted. Hard spaces = �(31).
D
Nh.startuphelp EQUS "The "+prog$+" utility provides a trash can icon on the icon bar, and uses "
X� EQUS "the Filer to display the trash can contents."+cr$+�(10)+"Do not use *"+command$+", use *Desktop instead."+bl$
b ALIGN
l
v1; PHEW ! Now let's get down to some coding...
�
�.internalreset
�
�I; An internal task variable is set to zero (not running) on execution
�K; of the Initialisation code, at the end of a machine (soft !) reset or
�<; when an old task is shutdown (to prevent duplication).
�
�) STMFD R13!,{R0,R14}
�! MOV R0,#0
�K STR R0,taskhandle ; Task not running, not claimed
�H STR R0,sparktaskhand; Don't know about Spark yet
�D STR R0,sparkwindhand; or the window involved
�> STRB R0,glassstat ; Hourglass is off
( LDMFD R13!,{R0,PC}
.servicecall
*<; The location 'taskhandle' holds the state of the task:
4:; 0 = Not running, waiting to claim Service_StartWimp
>H; -1 = Not running, claimed Service_StartWimp, waiting for * command
HE; >0 = Running, value set to Wimp_Initialise returned task handle
R
\K; The Service_Reset signal (Service Call &27) is the �LY way (I know..)
fI; to execute module code at the end of a machine reset. I use this to
p(; shutdown the task if still active.
z7; II-681 ---> DOESN'T TELL YOU to refer to III-1161
�
�L CMP R1,#Service_Reset ; End of machine reset ?
�E BEQ init ; Yes, so restart
�
�H; The very first thing that the Desktop does after a Wimp_Initialise
�H; is to signal Service_StartWimp (Service Call &49) to every module.
�J; Those that are interested in being trendy (OK, multi-tasking), claim
�D; that service call � THEY ARE � ALREADY RUNNING and, of course,
�?; haven't already received and claimed a Service_StartWimp.
�L; II-701 ---> annoyingly referring to the rough 'Window Manager' chapter
�G; (turns out, after much page scanning, to be III-1159)
�
�J CMP R1,#Service_StartWimp ; Are we firing up the
? BEQ round1 ; Desktop ?
D; Once everyone's responded to Service_StartWimp who wants to, a
$@; 'final chance' is sent around - Service_StartedWimp (&4A).
.H; II-702 ---> annoyingly (vaguely, like above) referring to III-1161
8
BH CMP R1,#Service_StartedWimp ; Round 2 of Desktop
L" BEQ round2
V
`K MOV PC,R14 ; Not interested in any of them
j
t).round1 STMFD R13!,{R2,R14}
~) LDR R2,taskhandle
�I MOVS R2,R2 ; Is taskhandle = 0 ?
�M MVNEQ R2,#0 ; Yes, so taskhandle = -1
�) STREQ R2,taskhandle
�I; Claim the Service Call because not running and not prev. claimed it
�J ADREQ R0,startupname ; => *Desktop_Trashcan
�A �Q R1,#0 ; Claim the call
�( LDMFD R13!,{R2,PC}
�
�.round2
�
�D; Since the * command may have failed, the task handle should be
�); set to 0 if it's still stuck at -1.
) STMFD R13!,{R2,R14}
) LDR R2,taskhandle
J MOVS R2,R2 ; Is taskhandle = -1 ?
(I MOVMI R2,#0 ; Stuck, so unstick !
2) STRMI R2,taskhandle
<( LDMFD R13!,{R2,PC}
F
P
.claimRMA
Z
d0; On entry, R3 = RMA space required
n6; On exit, R2 = Pointer to claimed space
x
�) STMFD R13!,{R0,R14}
�7 MOV R0,#6 ; Claim RMA
�4.joinclaim SWI "XOS_Module" ; II-655
�( ADRVS R0,poorclaim
�: SWIVS "OS_GenerateError" ; I-41
�( LDMFD R13!,{R0,PC}
�.poorclaim EQUD 0
�7 EQUS "RMA workspace failure"+bl$
� ALIGN
�
�.releaseRMA
�
�=; On entry, R2 = Pointer to space to be released
) STMFD R13!,{R0,R14}
9 MOV R0,#7 ; Release RMA
"% B joinclaim
,
6.startupcomm
@
JD; Once Service_WimpStart has been claimed, the Desktop will call
TG; Wimp_StartTask with R0 = * command addr returned by the claimant.
^H; Unfortunately, you can't dive straight in and start executing your
hD; code - you have to call OS_Module 2 (Enter Application) first.
r
|, STMFD R13!,{R0-R2,R14}
�M MOV R2,R0 ; Point to * command tail
�N MOV R0,#0 ; How many tasks running ?
�> SWI "XWimp_ReadSysInfo" ; III-1284
�E MOVS R0,R0 ; None, so not in
�= ADREQ R0,notindesktop ; Desktop
�. SWIEQ "OS_GenerateError"
�J ADR R1,titlestr ; Point to module name
�G MOV R0,#2 ; Enter Application
�< SWI "XOS_Module" ; II-651
�+ LDMFD R13!,{R0-R2,PC}
�.notindesktop EQUD 0
�B EQUS "Use *Desktop to start the "+prog$+bl$
� ALIGN
.leavenow
&K; User-instigated quit requested, so shutdown task and leave gracefully
0H; On entry, R9 = 0 for Temporary Quit, 1 for Permanent Quit
:E; = -1 for main (rather than sub) menu Quit
DM; For the moment, R9 = -1 is treated as a Permanent Quit (happy Philip ?)
N
XC BL wimpclosedown ; All done, so shutdown
b8 MOVS R9,R9 ; Severity of Quit ?
l �Q R1,#0
v �Q R2,#0
�? SWIEQ "OS_Exit" ; 0 = Mild ! II-743
�8 ADR R0,trashname1 ; First name
�6 MVN R2,#0 ; Delete variables
�0 MOV R3,#0 ; First call
�3 MOV R4,#0 ; Normal string
�F SWI "XOS_SetVarVal" ; Delete Trash$Dir. II-752
�9 ADR R0,trashname2 ; Second name
�0 MOV R3,#0 ; First call
�3 MOV R4,#0 ; Normal string
�B SWI "XOS_SetVarVal" ; Delete TrashWork$Dir
�! MOV R0,#0
�! MOV R1,#0
�! MOV R2,#0
' ADR R3,titlestr
G SWI "OS_ExitAndDie" ; -1 or 1 = Severe ! II-758
+.trashname1 EQUS "Trash$Dir"+bl$
/.trashname2 EQUS "TrashWork$Dir"+bl$
* ALIGN
4
>.registerspark
H
R7; On entry, R5 = Spark's "new" task handle
\
f) STMFD R13!,{R0,R14}
pA LDR R0,sparktaskhand; Get old task handle
z> CMP R0,R5 ; Is it new info ?
�B STRNE R5,sparktaskhand; Save new task handle
�C BLNE redocontents ; Update trash can icon
�( LDMFD R13!,{R0,PC}
�
�.inituserarea
�
�K; After about 75 million different attempts at coding using OS_SpriteOp
�H; only, OS_SpriteOp mixed with Wimp_SpriteOp and Wimp_SpriteOp only,
�J; I came to following conclusions regarding Wimp programs and sprites:
�F; 1) Use Wimp_SpriteOp for reading Sprite files and plotting them.
�L; 2) Use OS_SpriteOp 16 for saving a rect to a sprite (saves background)
�:; and OS_SpriteOp 34 for replotting that saved rect
�H; 3) Setup RMA workspace (claim and then call OS_SpriteOp 9) for the
D; OS_SpriteOp 16/34 calls - do � use the System Sprite area !
, STMFD R13!,{R0,R1,R14}
$J MOV R0,#spritespace%; Space needed for Van sprites
.H LDR R1,spritearea ; Offset 0 = Total area size
8# STR R0,[R1]
BG MOV R0,#0 ; Offset 4 = No sprites yet
L& STR R0,[R1,#4]
V" MOV R0,#16
`J STR R0,[R1,#8] ; Offset 8 = No extension area
jI STR R0,[R1,#12] ; Offset 12 = First free word
tL MOV R0,#9 ; Initialise sprite area (*SNew)
~3 BL spriteop ; I-398
�+ LDMFD R13!,{R0,R1,PC}
�
�).dummyspark STMFD R13!,{R3,R14}
�J LDR R3,sparktaskhand ; Only send if Spark's
�D MOVS R3,R3 ; handle unknown
�G LDREQ R3,windowspace ; Point to start of command
�4 ADDEQ R3,R3,#20 ; buffer
�I BLEQ sendittospark ; Tell everyone to do nothing
�( LDMFD R13!,{R3,PC}
�
�/.delsparkfile STMFD R13!,{R0,R2,R3,R14}
�( ADR R0,savedleaf
F LDR R3,putleafhere ; Set up when drag started
@.retrieveleaf LDRB R2,[R0],#1 ; Copy leaf onto end
& STRB R2,[R3],#1
! MOVS R2,R2
(( BNE retrieveleaf
2G BL sendittospark ; Tell Spark to delete file
<. LDMFD R13!,{R0,R2,R3,PC}
F
P,.sendittospark STMFD R13!,{R0-R3,R14}
ZG MOV R0,#13 ; Needs CR at end of command
d& STRB R0,[R3],#1
n! MOV R0,#0
x&.padtoword STRB R0,[R3],#1
�9 TST R3,#%11 ; Pad to word
�% BNE padtoword
�* LDR R1,windowspace
�L SUB R0,R3,R1 ; Size (inc. leaf/data) of block
�, LDR R2,sparktaskhand
�F LDR R3,sparkcommID ; Spark command message ID
�( BL sendamessage
�+ LDMFD R13!,{R0-R3,PC}
�A.sparkcommID EQUD &41000+61 ; Do Spark command ID
�
�.sendamessage
�
�3; On entry, R0 = Size of message block
G; R1 = Pointer to message (usu. Wimp_Poll) block
8; R2 = Task handle (0 = everyone)
,; R3 = Message action
"
,) STMFD R13!,{R0,R14}
6@ STR R0,[R1] ; Store block length
@! MOV R0,#0
JK STR R0,[R1,#12] ; my_ref = 0 (Original message)
TB STR R3,[R1,#16] ; Store message action
^" MOV R0,#18
h: SWI "XWimp_SendMessage" ; III-1253
r( LDMFD R13!,{R0,PC}
|
�
.appstart
�
�H; Well, here's the start sequence at last ! We only want one of this
�C; task running, so must shut down the old one if it is running.
�
�H LDR R13,workspace ; Reset stack pointer -> RMA
�@ BL wimpclosedown ; Shut down old task
�L MOV R0,#windman% ; Expecting V2.00 Window Manager
�J LDR R1,taskconstant ; Indicate new-style Wimp task
�J ADR R2,description ; English text name of program
�E SWI "XWimp_Initialise" ; Start task. III-1173
�I CMP R0,#windman% ; Are we earlier than V2.00 ?
�? ADRLT R0,notrecentwimp; Yes, so crash out
. SWILT "OS_GenerateError"
C STR R1,taskhandle ; Save Wimp task handle
&I; At the point, everything is ready for application initialisation...
0
:H BL dummyspark ; Try and get Spark to reply
DL BL loadtemplate ; Load template/make Info window
NF BL scantrashspr ; Load application sprites
X> BL readCMOS ; Setup menu ticks
b8 MOV R10,#0 ; First scan
cA STRB R10,dragstate ; Assume button is up
l< BL checkcontents ; Scan trash can
vD BL scanvanspr ; Load animation sprites
�
�H; Because applications could rename/delete/copy etc. in a variety of
�B; ways (and not using the WIMP), then have to claim UpCallV to
�+; trap any directory-changing activity.
�
�: MOV R0,#UpCallV ; I-68
�) ADR R1,trapupcall
�! MOV R2,#0
�: SWI "XOS_Claim" ; I-58
�
�L; ...and a tight Wimp_Poll loop, only quitting when the user requests it
�
�E.intightloop MOV R0,#0 ; All reason codes wanted
F SUB R1,R13,#stackspace% ; Data returned to RMA
6 SWI "XWimp_Poll" ; III-1192
H LDR R13,workspace ; Reset stack pointer -> RMA
: MOVS R0,R0 ; Is it idle ?
*( BNE actuallybusy
4I BL stopglass ; Yes, so Hourglass off if on
>J BL checkfordrag ; Are we dragging from Spark ?
HJ B checkfsflag ; See if Trash$Dir has changed
RM.actuallybusy CMP R0,#6 ; Check for mouse click. III-1196
\( BNE maybemenusel
f> LDR R0,[R1,#8] ; Get button state
pC CMP R0,#4 ; Is it left button...?
zF CMPNE R0,#1 ; ...or the right button ?
�' BNE maybemiddle
�I LDRB R0,CMOSbyte ; Only do something if not in
�< TST R0,#%001 ; Immediate mode
�C BLEQ peepincan ; Look inside trash can
�' B intightloop
�!.maybemiddle CMP R0,#2
�C BLEQ makenewmenu ; Middle button -> menu
�' B intightloop
�!.maybemenusel CMP R0,#9
�( BNE nomouseclick
�F MOV R2,R1 ; Save Wimp_Poll block ptr
�F ADD R1,R1,#&100 ; Pointer block further on
�> SWI "XWimp_GetPointerInfo" ; III-1214
> LDR R0,[R1,#8] ; Get button state
I MOV R1,R2 ; Restore Wimp_Poll block ptr
J BL dealwithmenu ; Menu item selected. III-1199
$F CMP R0,#1 ; Is it the right button ?
.A BLEQ makeoldmenu ; Keep menu on screen
8' B intightloop
BC.nomouseclick CMP R0,#2 ; Info window dragged ?
L= BNE maybemessage ; (Philip Colmer)
V> SWI "XWimp_OpenWindow" ; III-1190
`E B intightloop ; That was nice'n'easy...
jI.maybemessage CMP R0,#17 ; Check for message broadcast
t6 CMPNE R0,#18 ; III-1202
~' BNE checkfsflag
�' LDR R2,[R1,#16]
�! MOVS R2,R2
�@ �Q R9,#0 ; Signal Temporary Quit
�F BEQ leavenow ; Quit requested. III-1255
�$ MOV R3,#&500
�= ADD R3,R3,#2 ; !Help ID = &502
�C CMP R3,R2 ; Was !Help requested ?
�& BNE wasitadrag
�= LDR R2,[R1,#32] ; Get icon handle
�@ CMN R2,#-iconbartype% ; Icon bar ?
�H MOVNE R4,#1 ; No, so must be Info Window
�A BNE helpwanted ; Rejoin help request
= LDR R2,[R1,#36] ; Is it my icon ?
) LDR R3,iconhandle
! CMP R2,R3
' BNE intightloop
(E MOV R4,#0 ; Flag that it's the icon
2B.helpwanted BL askedforhelp ; !Help info requested
<' B intightloop
FC.wasitadrag CMP R2,#3 ; Load data requested ?
P6 BNE maybespark ; III-1265
ZE LDR R2,[R1,#20] ; Is it on the icon bar ?
d- CMN R2,#-iconbartype%
n' BNE intightloop
x= LDR R2,[R1,#24] ; Is it my icon ?
�) LDR R3,iconhandle
�! CMP R2,R3
�I BLEQ moveintotrash ; File dragged onto trash can
�' B intightloop
�L.maybespark LDR R3,dyingappmess ; Has an application just died ?
�, LDR R4,sparktaskhand
�F LDR R5,[R1,#4] ; Get task handle involved
�! CMP R2,R3
�< CMPEQ R5,R4 ; Was it Spark ?
�G �Q R5,#0 ; If so, forget Spark's handle
�C BEQ sparkchange ; Return icon to normal
�C LDR R3,reptaskname ; Is it the task handle
�; CMP R2,R3 ; translation ?
) BNE didsparkstart
B ADR R0,sparktaskname; Spark's task name...
% ADD R2,R1,#28
"D.scanningname LDRB R3,[R0],#1 ; ...compare it with the
,K LDRB R4,[R2],#1 ; returned name to find a match
6! CMP R3,R4
@' BNE intightloop
JA MOVS R3,R3 ; Still scanning name
T( BNE scanningname
^K LDR R5,[R1,#20] ; Retrieve handle matching name
h' B sparkchange
rI.didsparkstart LDR R3,sparkmessid ; Has Spark just started up ?
|! CMP R2,R3
�J BEQ sparkchange ; OK, time to know about Spark
�B LDR R3,sparkcommID ; Was Spark replying ?
�! CMP R2,R3
�K BNE whataboutsave ; Not a response to dummy bcast
�I; At this point, received response from dummy Spark broadcast, so ask
�C; about the name matching the task handle (in R5 at the moment)
�= MOV R0,#24 ; Size = 24 bytes
�? MOV R2,#0 ; General broadcast
�M LDR R3,reqtaskname ; Request task handle translation
�? STR R5,[R1,#20] ; Store task handle
�( BL sendamessage
�' B intightloop
�@.whataboutsave CMP R2,#1 ; DataSave request ?
L BNE intightloop ; (Spark'ed file onto Trash Can)
H CMP R4,R5 ; Check task handle involved
N BNE intightloop ; belongs to Spark and no-one else
&! MOV R2,R4
09 LDR R3,[R1,#8] ; Copy my_ref
:' STR R3,[R1,#12]
D9 MOV R3,#2 ; DataSaveAck
N' STR R3,[R1,#16]
XG MVN R3,#0 ; Set file to 'unsafe' (-1)
b' STR R3,[R1,#36]
l% ADD R3,R1,#44
v( ADR R4,savedleaf
�B.savetheleaf LDRB R5,[R3],#1 ; Save suggested Spark
�D STRB R5,[R4],#1 ; leafname for use later
�! MOVS R5,R5
�' BNE savetheleaf
�, ADR R3,tempsparkname
�% ADD R4,R1,#44
�D.copyscrapname LDRB R5,[R3],#1 ; Temporary filename for
�J STRB R5,[R4],#1 ; decompression = <Wimp$Scrap>
�! MOVS R5,R5
�) BNE copyscrapname
�C SWI "XWimp_SendMessage" ; Spark->decompress
�' B intightloop
�J.sparkchange BL registerspark ; Save Spark handle if changed
J BL dummyspark ; Re-broadcast in case there's
A B intightloop ; 2 or more Sparks...
F.sparkmessid EQUD &41000+60 ; Spark started message ID
C.dyingappmess EQUD &400C3 ; Message_TaskCloseDown
*@.reqtaskname EQUD &400C6 ; Message_TaskNameRq
4@.reptaskname EQUD &400C7 ; Message_TaskNameIs
>-.tempsparkname EQUS "<"+wimp$+">"+bl$
H ALIGN
R'.sparktaskname EQUS "Spark"+bl$
\ ALIGN
f
pL.checkfsflag LDRB R10,fsctrlflag ; This is why we need all reason
zM MOVS R10,R10 ; codes - at any time there could
�F BLNE checkcontents ; be an FS action changing
�7 B intightloop ; Trash$Dir
�
�%.description EQUS prog$+bl$
� ALIGN
�.sparktaskhand EQUD 0
�.sparkwindhand EQUD 0
�.notrecentwimp EQUD 0
�b EQUS prog$+" requires Window Manager V"+�fraction(windman%)+" or later"+bl$
� ALIGN
�
� .init
�
D; This routine is called when the module is first loaded, when a
?; *RMReInit is called or when a machine reset is signalled.
$, STMFD R13!,{R2,R3,R14}
.@ BL internalreset ; Only want to reset
8A MOV R3,#stackspace% ; Claim RMA for stack
BD LDR R2,workspace ; See if already claimed
L! MOVS R2,R2
V$ BLEQ claimRMA
`H ADDEQ R2,R2,R3 ; Adjust to end of workspace
jH STREQ R2,workspace ; cos stack builds downwards
tD �Q R3,#windowspace%; Claim RMA for window info
~$ BLEQ claimRMA
�* STREQ R2,windowspace
�I �Q R3,#spritespace%; Claim RMA for sprite workspace
�$ BLEQ claimRMA
�) STREQ R2,spritearea
�+ LDMFD R13!,{R2,R3,PC}
�.workspace EQUD 0
�.windowspace EQUD 0
�.spritearea EQUD 0
�/.savedleaf EQUS �11,bl$) ; Filename
� ALIGN
�
�.changeicon
G; On entry, R1 = � "1" for thin trash can, � "2" for thick
2; This routine has been added to V1.02 onwards
M; Entry param different in V1.10 onwards for new thin can (Philip Colmer)
(6; Now adds 2 to R1 if Spark's task handle is known
2
<, STMFD R13!,{R0,R1,R14}
FM LDR R0,sparktaskhand; Do we know Spark's handle yet ?
P! MOVS R0,R0
ZJ ADDNE R1,R1,#2 ; Yes, so use 'flashy' sprites
d+ LDRB R0,spritename+6
nK CMP R0,R1 ; No point in call if no change
x@ STRNEB R1,spritename+6 ; Toggle sprite name
�+ ADRNE R1,iconstateblk
�5; Boy - my favourite opcode is on the next line !
�M SWINE "XWimp_SetIconState" ; III-1211. Avoid shuffle
�+ LDMFD R13!,{R0,R1,PC}
�(.iconstateblk EQUD iconbartype%
�.iconhandle EQUD 0
�J EQUD 0 ; � word ; Both words set to zero
�L EQUD 0 ; Clear word ; because flags the same
�
�
.makeicon
�
�G; On entry, R1 = � "1" for thin trash can, � "2" for thick
�K; Note - Sprites should be called '!trash1' and '!trash2' - do � rename
M; Entry param different in V1.10 onwards for new thin can (Philip Colmer)
, STMFD R13!,{R0,R1,R14}
"> STRB R1,spritename+6 ; Poke name ending
,) ADR R1,spritename
6) STR R1,pokespname
@( ADR R1,iconblock
J> SWI "XWimp_CreateIcon" ; III-1180
T) STR R0,iconhandle
^+ LDMFD R13!,{R0,R1,PC}
hG; This is a data block for Wimp_CreateIcon - fixed by Philip Colmer
rE.iconblock EQUD iconbartype% ; Icon bar 'service' flag
|; EQUD 0 ; Bottom left X
�; EQUD 0 ; Bottom left Y
�9 EQUD 69 ; Top right X
�9 EQUD 68 ; Top right Y
�> EQUB %00000010 ; Icon is a sprite
�G EQUB %00110001 ; Click notifies/Indirected
�H EQUB %00000000 ; Nothing special about icon
�F EQUB %00000001 ; Forecol = 1, Backcol = 0
�D.pokespname EQUD 0 ; Pointer to sprite name
�E EQUD 1 ; Pointer to WIMP sprites
� EQUD 12
�:.spritename EQUS "!trash"+�6,bl$) ; Sprite name
�
�H; 'killicon' routine removed from V1.02 onwards - no longer required
.trapupcall
&F; Thanks to Philip Colmer for the reason codes here - the old PRMs
0E; only list R0=1 and R0=&100, so I had no idea about R0=3 ! I-139
:C; On entry, R0 = Reason code (3 for file modification)
D@; R9 = File modification reason (if R0=3)
N
X) STMFD R13!,{R9,R14}
bK CMP R0,#3 ; Only if modification notified
l& BNE notfilemod
v7 CMP R9,#0 ; *Save (0)
�9 CMPNE R9,#6 ; *Delete (6)
�9 CMPNE R9,#7 ; *Create (7)
�7 CMPNE R9,#8 ; *CDir (8)
�G SUB R9,R9,#256 ; Can't get 257 immediately
�J CMPNE R9,#1 ; Open/Create for update (257)
�G SUB R9,R9,#256 ; Can't get 520 immediately
�; CMPNE R9,#8 ; *Rename (520)
�F �Q R9,#1 ; Although can't be sure, set
�E STREQB R9,fsctrlflag ; changed flag to be safe
�(.notfilemod LDMFD R13!,{R9,PC}
�
�.wimpclosedown
�
K; This (handy) routine will only call Wimp_CloseDown if Wimp_Initialise
H; had successfully been executed (i.e. taskhandle > 0). It then sets
I; taskhandle to 0 to indicate shutdown. Note that Wimp_CloseDown also
&; handily kills the icon bar icon.
*
4, STMFD R13!,{R0-R2,R14}
>I LDR R0,taskhandle ; Is taskhandle > 0 ?
H! MOVS R0,R0
R' BLE dormanttask
\E BL notrashwind ; Remove Trash Can Window
f= MOV R0,#UpCallV ; Release UpCallV
p) ADR R1,trapupcall
z! MOV R2,#0
�2 SWI "XOS_Release" ; I-59
�J BL checkforred ; Remove red border if present
�) LDR R0,taskhandle
�+ LDR R1,taskconstant
�G SWI "XWimp_CloseDown" ; Shutdown task. III-1241
�!.dormanttask MOV R0,#0
�? STR R0,iconhandle ; Clear icon handle
�? STR R0,taskhandle ; Clear task handle
�@ STR R0,sparktaskhand; Clear Spark handle
�L STR R0,templatehandle ; Templates will need a reload
�? STRB R0,modifiedbord ; No red border yet
�+ LDMFD R13!,{R0-R2,PC}
�@.taskconstant EQUS "TASK" ; Special four-letter word !
L.taskhandle EQUD 0 ; Wimp task handle (also used as a flag)
.peepincan
$
.J; Want to have a look inside trash can, so create the directory if not
8@; already there and use the Filer to create a new Wimp task.
B
L) STMFD R13!,{R0,R14}
VG BL canexists ; Make sure Trash$Dir is OK
`
jI; Stupid *Filer_OpenDir <dir> doesn't translate environmental vars !!
t'; Hence must use translated buffer.
~
�* ADR R0,startupwind
�: SWI "XWimp_StartTask" ; III-1242
�( LDMFD R13!,{R0,PC}
�
�.readtrashdir
�
�L; On entry, R1 = Address of buffer to store Trash$Dir expansion
�E; MUST have Trash$Dir defined at all times, otherwise fatal error
�
�, STMFD R13!,{R0-R4,R14}
�! MOV R0,#0
�( STRB R0,poketrash
) ADR R0,plaintrash
K MOV R2,#maxpathlen%-1 ; Reduced by 1 (Rabin).
! MOV R3,#0
! MOV R4,#0
(< SWI "XOS_ReadVarVal" ; II-750
2! MOVVC R0,#0
<L STRVCB R0,[R1,R2] ; Add a zero terminator (Rabin).
F+ LDMVCFD R13!,{R0-R4,PC}
P3; This section revamped by Rabin Ezra. Thanks !
ZA MOVS R2,R2 ; Is error overflow ?
d+ ADREQ R0,undefinedvar
n) ADRNE R0,vartoolong
x. SWI "OS_GenerateError"
�).plaintrash EQUS trashvar$+bl$
�>.startupwind EQUS "Filer_OpenDir " ; III-1292
�-.trashopenbuff EQUS �maxpathlen%,bl$)
�>.closedownwind EQUS "Filer_CloseDir " ; III-1291
�-.trashclosebuff EQUS �maxpathlen%,bl$)
� ALIGN
�.vartoolong EQUD 0
�o EQUS trashvar$+" environmental variable longer than "+�(maxpathlen%-1)+" characters"+bl$
� ALIGN
�.undefinedvar EQUD 0
�M EQUS trashvar$+" environmental variable undefined"+bl$
�.fsctrlflag EQUB 0
�.glassstat EQUB 0
.CMOSbyte EQUB 0
.dragstate EQUB 0
ALIGN
",.notrashwind STMFD R13!,{R0,R1,R14}
,- ADR R1,trashclosebuff
6C BL readtrashdir ; Get Trash$Dir
@
JG; Note that because the Wimp may already be partially shut down, we
T?; can't use XWimp_StartTask in this section, so use XOS_CLI
^
h, ADR R0,closedownwind
rK SWI "XOS_CLI" ; Shutdown Trash window. II-619
|+ LDMFD R13!,{R0,R1,PC}
�
�.checkcontents
�
�I; On entry, R10 = 0 if want to create icon, <> 0 to update it
�H; Want to decide what icon to put on icon bar, so check the contents
�L; of <Trash$Dir>. If the env. variable doesn't exist, or the dir doesn't
�?; exist or there's nothing in the dir, then trash is empty.
�
�, STMFD R13!,{R0-R3,R14}
�, ADR R1,trashopenbuff
�= BL readtrashdir ; Trash$Dir check
�$ MOV R0,#�"."
�( STRB R0,poketrash
! MOV R0,#5
( ADR R1,trashbits
J SWI "XOS_File" ; Any <Trash$Dir>.* files ? III-850
&( LDR R2,trashstat
0I �R R2,R2,#(1<<22) ; Bit 22 set to indicate empty
:! BVS empty
DH LDRB R3,CMOSbyte ; If in Immediate mode, then
NI TST R3,#%001 ; trash can is always 'empty'
X! BNE empty
b! MOVS R0,R0
lI BICNE R2,R2,#(1<<22) ; Bit 22 cleared because full
v(.empty STR R2,trashstat
�% BL updatecan
�+ LDMFD R13!,{R0-R3,PC}
�-.trashbits EQUS "<"+trashvar$+">"
�'.poketrash EQUS bl$+"*"+bl$
� ALIGN
�
�.redocontents
�
�M; Like checkcontents, but uses last scan for info rather than re-scanning
�
�- STMFD R13!,{R2,R10,R14}
�; LDR R2,trashstat ; Get last scan
�> MOV R10,#1 ; Flag icon update
!% BL updatecan
!, LDMFD R13!,{R2,R10,PC}
!
! .updatecan
!*
!4-; On entry, R2 = Trashstat value
!>I; R10 = 0 if want to create icon, <> 0 to update it
!H
!R) STMFD R13!,{R1,R14}
!\' TST R2,#(1<<22)
!fA MOVNE R1,#�"1" ; Empty flag (Philip Colmer)
!p- �Q R1,#�"2" ; Full flag
!zH MOVS R10,R10 ; Is this the first time the
!�L BLEQ makeicon ; icon is to appear on the bar ?
!�& BLNE changeicon
!�! MOV R1,#0
!�F STRB R1,fsctrlflag ; No need for more updates
!�( LDMFD R13!,{R1,PC}
!�
!�.canexists
!�
!�5; Must create trash directory if it doesn't exist
!�
!�, STMFD R13!,{R0,R1,R14}
!�, ADR R1,trashopenbuff
!�L BL readtrashdir ; Make sure Trash$Dir var exists
"! MOV R0,#0
"( STRB R0,poketrash
"( ADR R1,trashbits
"$! MOV R0,#8
".H SWI "XOS_File" ; *CDIR <Trash$Dir>. III-854
"8+ LDMFD R13!,{R0,R1,PC}
"B
"L-.newname EQUS "<"+trashvar$+">"
"V(.nameending EQUS "."+�11,bl$)
"` ALIGN
"j
"t.getcaniconinfo
"~
"�N; On exit, R2 = Right-hand X coord of trash can icon on icon bar
"�
"�, STMFD R13!,{R1,R3,R14}
"�C MVN R2,#-(iconbartype%+1) ; Icon bar type
"�C LDR R3,iconhandle ; Trash can icon handle
"�' BL geticoninfo
"�D LDR R2,[R1,#16] ; Get icon right X coord
"�+ LDMFD R13!,{R1,R3,PC}
"�
"�.geticoninfo
"�
"�+; On entry, R0 = Window handle
# ); R2 = Icon handle
#
7; On exit, R1 = Pointer to IconState info
#
#L ADR R1,(trashclosebuff+3) � 4*4 ; Recycle workspc
#(A STR R2,[R1] ; Store window handle
#2? STR R3,[R1,#4] ; Store icon handle
#<M SWI "XWimp_GetIconState" ; Get icon info. III-1213
#F" MOV PC,R14
#P
#Z.moveintotrash
#d
#n8; On entry, R1 = Pointer to Wimp_Poll block
#x
#�/ STMFD R13!,{R0-R6,R9,R14}
#�B LDRB R5,CMOSbyte ; Get Immediate option
#�% � R5,R5,#%001
#�: BL startglass ; Hourglass on
#�? ADD R3,R1,#44 ; Point to filename
#�H BL canexists ; Create Trash dir if needed
#�
#�H; Because *Rename is extremely awkward about wildcards - won't allow
#�J; them (ARRGGHH !) - have to copy the name (from the last '.' onwards)
#�
#�@ LDR R4,[R3,#-44+12] ; Is it from Filer ?
#�! MOVS R4,R4
#�F BEQ itsfromFiler ; Yes, so endings the same
$, LDR R0,sparktaskhand
$; LDR R1,[R3,#-44+4] ; Is it Spark ?
$! CMP R0,R1
$"; BNE canttrash ; No, so ignore
$,F ADR R0,savedleaf ; and copy leafname to the
$6> ADR R1,nameending+1 ; end of Trash$Dir
$@&.copysafeleaf LDRB R2,[R0],#1
$J& STRB R2,[R1],#1
$T! MOVS R2,R2
$^( BNE copysafeleaf
$h' B retryaccess
$r!.itsfromFiler MOV R0,R3
$|< MOV R2,#0 ; Don't poke yet
$�&.lookingforend LDRB R1,[R0],#1
$�C CMP R1,#�"." ; Still traversing dirs ?
$�) ADREQ R2,nameending
$�! MOVS R2,R2
$�F STRNEB R1,[R2],#1 ; Copy text into dest name
$�! MOVS R1,R1
$�B BNE lookingforend ; Got terminator yet ?
$�
$�D; Next bit added to V1.01 to make sure that *Rename ALWAYS works
$�M; if the file is on the same disk (avoiding having to *Copy locked files)
$�
$�H.retryaccess MOV R0,#24 ; *Access <file> WR. III-910
$�H MOV R1,R3 ; Point to original filename
%G ADR R2,attributes ; Point to WR access string
%' BL dofscontrol
%% BGT canttrash
%&%.retryrename STMFD R13!,{R3}
%0! MOV R1,R3
%:A MOVS R5,R5 ; Immediate enabled ?
%DG �Q R0,#25 ; *RENAME reason code. III-911
%N& ADREQ R2,newname
%X> SWIEQ "XOS_FSControl" ; *Rename. III-911
%b* BEQ attemptnewname
%lJ ADR R6,callwipe ; (Optionally) animate van and
%vM MOV R9,R1 ; *Wipe everything from Trash$Dir
%�* BL dovananimation
%�* B attemptnewname
%�,.callwipe STMFD R13!,{R0-R3,R14}
%�H MOV R0,#27 ; *WIPE reason code. III-915
%�! MOV R1,R9
%�J MOV R3,#%010000011 ; ~QF~CR~V and delete original
%�< SWI "XOS_FSControl" ; *Wipe. III-915
%�+ LDMFD R13!,{R0-R3,PC}
%�%.attemptnewname LDMFD R13!,{R3}
%�E BVC acknowledge ; Good, so acknowledge it
%�
%�F; To prevent the silly copy of Trash into itself (causes 77 levels
%�A; to be created !), the error code for Bad RENAME is checked.
&
&@ LDR R1,[R0] ; Get the error word
&( LDR R2,badrename
& E CMP R1,R2 ; = &108B0 (Bad RENAME) ?
&*% BEQ canttrash
&4
&>D; The only (non-fatal) way a rename can fail is if the rename is
&HE; attempted across disks/FSs or into itself (when it's a dir)....
&R
&\& LDR R2,baddisk
&fH CMP R1,R2 ; = &1089F (Not same disc) ?
&pB CMPNE R1,#&B0 ; = &B0 (Bad rename) ?
&z
&�H; ...or if it is already present in Trash$Dir (Already exists error)
&�
&�( LDRNE R2,doublecan
&�I CMPNE R1,R2 ; = &108C4 (Already exists) ?
&�' BEQ dotrashcopy
&�
&�0; If it gets here, then there's a disk fault
&�
&�) BL generateerror
&�! CMP R1,#1
&�' BEQ retryrename
&�% BGT canttrash
&�L.dotrashcopy MOVS R5,R5 ; If Immediate then *Wipe failed
'G BNE canttrash ; so don't do anything else
'H MOV R0,#26 ; *COPY reason code. III-912
'! MOV R1,R3
'$& ADR R2,newname
'.: BL dofscontrol ; Do the *COPY
'8% BGT canttrash
'B
'LD; This code added for V1.01 - should have been in V1.00...sorry.
'V
'`:.acknowledge MOV R0,#17 ; User message
'jD SUB R1,R3,#44 ; Go back to block start
'tI LDR R2,[R1,#8] ; Get unique reference number
'~H STR R2,[R1,#12] ; Store it in response field
'�! MOV R2,#4
'�9 STR R2,[R1,#16] ; DataLoadAck
'�F LDR R2,[R1,#4] ; Get task handle involved
'�C SWI "XWimp_SendMessage" ; Acknowledge drag
'�! MOVS R4,R4
'�? BLNE delsparkfile ; Delete Spark file
'�L.canttrash LDMFD R13!,{R0-R6,R9,PC} ; Return (FS flag may be set)
'�G.fakereturn MOV PC,R14 ; Fake return for animation
'�C.badrename EQUD &108B0 ; Bad RENAME error code
'�F.baddisk EQUD &1089F ; Not same disc error code
'�G.doublecan EQUD &108C4 ; Already exists error code
'�
( F; Note that PUBLIC read-write (/WR) has � been used because anyone
(
M; on Econet could hack around with the files whilst they're in the trash!
(
(@.attributes EQUS "WR"+bl$ ; *Access attributes
(( ALIGN
(2
(<.checkerror
(F
(PA; On entry, R0 = Points to an error block (if V set)
(ZL; On exit, ZC = LT if no error, EQ if OK clicked, GT if Cancel
(d
(n) STMFD R13!,{R1,R14}
(x! MOVVC R1,#0
(�) BLVS generateerror
(�C CMP R1,#1 ; Tacky, but it works !
(�( LDMFD R13!,{R1,PC}
(�
(�.generateerror
(�
(�6; On entry, R0 = Points to an error block
(�B; On exit, R1 = 1 if OK clicked, 2 if Cancel clicked
(�
(�, STMFD R13!,{R0,R2,R14}
(�G MOV R1,#%0000011 ; OK & Cancel, Highlight OK
(�( ADR R2,errorname
(�: SWI "XWimp_ReportError" ; III-1243
)F MOV R0,#0 ; Wimp_ReportError does an
)I STRB R0,glassstat ; Hourglass_Smash, so need to
)? BL startglass ; start it up again
)"+ LDMFD R13!,{R0,R2,PC}
),%.errorname EQUS prog$+bl$
)6 ALIGN
)@
)J.startglass
)T
)^H; Switch on Hourglass (busy delay = 1 second), but only if it is off
)h
)r) STMFD R13!,{R0,R14}
)|( LDRB R0,glassstat
)�! MOVS R0,R0
)�< �Q R0,#100 ; 1 second to start
)�( STREQB R0,glassstat
)�8 SWIEQ "XHourglass_Start" ; IV-1393
)�( LDMFD R13!,{R0,PC}
)�
)�.stopglass
)�
)�0; Switch off Hourglass, but only if it is on
)�
)�) STMFD R13!,{R0,R14}
)�( LDRB R0,glassstat
)�! MOVS R0,R0
*! MOVNE R0,#0
*( STRNEB R0,glassstat
*6 SWINE "XHourglass_Off" ; IV-1391
*&( LDMFD R13!,{R0,PC}
*0
*:.byebye
*D
*NI; This routine is called when the module is *RMKilled or *RMReInited.
*X
*b) STMFD R13!,{R2,R14}
*lL LDR R2,workspace ; Free (any) stack space
*vH SUBS R2,R2,#stackspace% ; Point to RMA start
*�& BLPL releaseRMA
*�J LDRPL R2,windowspace ; Release window space
*�& BLPL releaseRMA
*�I LDRPL R2,spritearea ; Release sprite area
*�& BLPL releaseRMA
*�K BL wimpclosedown ; Shut down active task
*�! MOV R2,#0
*�D STR R2,workspace ; Clear workspace flag
*�( LDMFD R13!,{R2,PC}
*�
*�,.readCMOS STMFD R13!,{R0-R2,R14}
*�H MOV R0,#161 ; Read CMOS RAM to get saved
*�F MOV R1,#battery% ; settings of menu options
+4 SWI "XOS_Byte" ; II-787
+I STRB R2,CMOSbyte ; Save for later modification
+K LDR R0,immediatestat ; Configure tick on Immediate
+ 9 MOV R1,#%001 ; Bit 0 first
+*& BL twiddlebit
+4, STR R0,immediatestat
+>G LDR R0,warningstat ; Configure tick on Warning
+H& BL twiddlebit
+R* STR R0,warningstat
+\J LDR R0,animationstat ; Configure tick on Animation
+f& BL twiddlebit
+p, STR R0,animationstat
+z+ LDMFD R13!,{R0-R2,PC}
+�
+�.twiddlebit
+�
+�.; On entry, R0 = Menu status word
+�0; R1 = Bit mask of status
+�); R2 = Status byte
+�;; On exit, R0 = New value of menu status word
+�/; R1 = Shifted left by 1
+�
+�) STMFD R13!,{R2,R14}
+�H BIC R0,R0,#(1<<0) ; Clear flag bit (0) on menu
+�" �S R2,R2,R1
+�H �RNE R0,R0,#(1<<0) ; Set flag bit if switched on
,K MOV R1,R1,ASL #1 ; Next menu is 1 bit on in CMOS
,( LDMFD R13!,{R2,PC}
,
,$.togglebit
,.
,88; On entry, R0 = Bit position to be toggled
,B
,L, STMFD R13!,{R0-R2,R14}
,VG MOV R1,#1 ; Straightforward � (1<<R0)
,`E LDRB R2,CMOSbyte ; Flip bit R0 in CMOS RAM
,j) � R2,R2,R1,ASL R0
,t# MOV R0,#162
,~( MOV R1,#battery%
,�E SWI "XOS_Byte" ; Update CMOS RAM. II-788
,�N BL readCMOS ; Re-read 'cos menu option changed
,�+ LDMFD R13!,{R0-R2,PC}
,�
,�.dealwithmenu
,�
,�8; On entry, R1 = Pointer to Wimp_Poll block
,�
,�6 STMFD R13!,{R0-R2,R6,R9,R10,R14}
,�F LDR R0,[R1] ; Get item number (from 0)
,�! MOVS R0,R0
,�I BEQ ignoremenu ; Item #1 = Info (do nothing)
- < CMP R0,#5 ; Item #6 = Quit
-
& LDREQ R9,[R1,#4]
-$ BEQ leavenow
-C CMP R0,#4 ; Item #5 = Empty Trash
-(( BEQ dothebinning
-2N; It it gets here, then must be Items #2-4 (Immediate, Warning, Animation)
-<H SUB R0,R0,#1 ; Invert tick on appropriate
-FJ BL togglebit ; menu (updating CMOS RAM too)
-PC MOVS R0,R0 ; Skip if not Immediate
-Z& BNE ignoremenu
-dL MOV R10,#1 ; If Immediate item toggled then
-nM BL checkcontents ; might need to re-enable fat can
-xK LDRB R0,CMOSbyte ; If Immediate toggled on, then
-�M TST R0,#%001 ; must shut down Trash Can Window
-�' BLNE notrashwind
-�& B ignoremenu
-�>; Must be Item #5, which is only enabled if there is Trash
-�,.dothebinning ADR R6,cleantrashdir
-�@ BL dovananimation ; Trundle van time !
-�5.ignoremenu LDMFD R13!,{R0-R2,R6,R9,R10,PC}
-�
-�.trashthestuff
-�
-�H; On entry, R6 = Address of routine to be used for trashing
-�
-�K MOV PC,R6 ; Not exactly tricky to code...
.
.,.cleantrashdir STMFD R13!,{R0,R1,R14}
.: BL startglass ; Hourglass on
."H MOV R0,#27 ; *WIPE reason code. III-915
.,( ADR R1,trashbits
.6' BL dofscontrol
.@+ LDMFD R13!,{R0,R1,PC}
.J
.T.dofscontrol
.^
.h6; On entry, R0 = OS_FSControl reason code
.r4; R1 = Pointer to source name
.|H; R2 = Pointer to dest name (not used with *WIPE)
.�
.�) STMFD R13!,{R3,R14}
.�$ MOV R3,#�"."
.�( STRB R3,poketrash
.�(.retrycopywipe STMFD R13!,{R0-R2}
.�J MOV R3,#%010000011 ; ~QF~CR~V and delete original
.�+ SWI "XOS_FSControl"
.�H BL checkerror ; Keep trying until no error
.�B LDMFD R13!,{R0-R2} ; or Cancel clicked on
.�) BEQ retrycopywipe
.�G LDMFD R13!,{R3,PC} ; Return (FS flag will be set)
.�
.�.checkfordrag
/M; On entry, R1 = Pointer to Wimp_Poll block (used for workspace)
/, STMFD R13!,{R0-R5,R14}
/2 SWI "XWimp_GetPointerInfo"
/&? LDR R2,[R1,#12] ; Get window handle
/0= LDR R3,[R1,#16] ; Get icon handle
/:J LDR R0,[R1,#8] ; Must have one of the buttons
/DB TST R0,#%101 ; down to start a drag
/N �Q R4,#0
/XK STREQ R4,sparkwindhand; If not, we don't know Spark's
/b; BEQ checkformenu ; window handle
/cH MOV R5,#1 ; Button down, away from can
/lE LDR R4,sparkwindhand; Skip if we already know
/vC MOVS R4,R4 ; Spark's window handle
/�) BNE couldbeoverme
/�G MOVS R3,R3 ; Only looking for an icon,
/�B BMI couldbeoverme ; not part of a window
/�I MOVS R4,R2 ; Make sure not background or
/�6 BMI couldbeoverme ; icon bar
/�* LDR R1,windowspace
/�" MOV R0,#20
/�8 STR R0,[R1] ; Block size
/�! MOV R0,#0
/�8 STR R0,[R1,#12] ; my_ref = 0
/�" MOV R0,#19
/�J SWI "XWimp_SendMessage" ; Ask for owner handle
/�, LDR R0,sparktaskhand
0C CMP R0,R2 ; Was it a Spark icon ?
0( BNE notsparkdrag
0F STR R4,[R1] ; Need to get more
0 G SWI "XWimp_GetWindowInfo" ; details. III-1210
0*> LDR R0,[R1,#28+4] ; Get window flags
04D MOV R0,R0,LSR #24 ; Get icon control flags
0>I BIC R0,R0,#(%11<<7) ; Ignore bit sel/horiz scroll
0H? CMP R0,#%111111 ; Are all enabled ?
0R( BNE notsparkdrag
0\) LDR R0,[R1,#56+4]
0fF TST R0,#(1<<8) ; Is title info indirect ?
0p( BEQ notsparkdrag
0z@ STR R4,sparkwindhand; Save window handle
0�, ADR R0,sparkrootcomm
0�, MOV R2,#�(sparkdel$)
0�% ADD R3,R1,#20
0�I.stillcommmove LDRB R4,[R0],#1 ; Copy start of Spark command
0�A STRB R4,[R3],#1 ; into workspace area
0�$ SUBS R2,R2,#1
0�) BNE stillcommmove
0�9 LDR R0,sparktaskhand; Source task
0�< LDR R4,[R1,#72+8+4] ; Size of buffer
0�E LDR R1,[R1,#72+4] ; Pointer to window title
0�> LDR R2,taskhandle ; Destination task
0�> SWI "XWimp_TransferBlock" ; III-1283
0�
1G; Although we 'think' we know the length of the window title, it is
1C; only the buffer size - must find the terminating zero instead
1
1$#.findpathzero LDRB R0,[R3]
1.! MOVS R0,R0
18$ ADDNE R3,R3,#1
1B( BNE findpathzero
1LH STR R3,putleafhere ; That's where the leaf goes
1V( B notsparkdrag
1`F.couldbeoverme CMN R2,#2 ; Window = -2 (icon bar) ?
1j) LDREQ R1,iconhandle
1t@ CMPEQ R1,R3 ; Icon = Trash Can ?
1~( BNE notsparkdrag
1�
1�H; If it gets here, then a button is down and the pointer is over the
1�; Trash Can icon.
1�
1�M LDRB R0,CMOSbyte ; Immediate and Warning enabled ?
1�$ � R0,R0,#%11
1�# CMP R0,#%11
1�( BNE notsparkdrag
1�
1�B; However, 'dragstate' must have been set to 1 (away from can,
1�I; button down) rather than 0 (button up) or 2 (over can, button down)
1�6; prior to this if we want to turn the border red.
2
2C MOV R5,#2 ; Over can, button down
2
( LDRB R0,dragstate
2! CMP R0,#1
2H BLEQ turnborderred ; OK, so warn user that he's
2(D B dontchange ; about to destroy files
22
2<&; At this point, R0 = Button state
2FK; R1 = GetPointerInfo block, R2/R3 = window/icon handles
2PE; Must see if pointer is over 'Empty Trash' (enabled) menu option
2Z
2d.checkformenu
2n]
2x� debug% �
2�[OPT A%
2�I BL showhandles ; Display handles in top left
2�]
2��
2�[OPT A%
2�F MOV R5,#0 ; Button up, away from can
2�K CMP R3,#5*3-2 ; On fifth item (Empty Trash) ?
2�( BNE notsparkdrag
2�? LDRB R0,CMOSbyte ; Warning enabled ?
2�$ � R0,R0,#%10
2�# CMP R0,#%10
2�( BNE notsparkdrag
2�H BL getmenuiconinfo ; Yes, so get menu item text
2�! MOV R4,#3
3H.scanformiss LDR R2,[R0],#4 ; Compare "Empty Trash" with
3F LDR R3,[R1],#4 ; menu item text to see if
3L CMP R2,R3 ; it's my menu (only easy way !)
3"( BNE notsparkdrag
3,$ SUBS R4,R4,#1
36' BNE scanformiss
3@H BL turnborderred ; Turn border red if on item
3J& B dontchange
3TI.notsparkdrag BL checkforred ; Not over can, so remove red
3h(.dontchange STRB R5,dragstate
3i+ LDMFD R13!,{R0-R5,PC}
3r.putleafhere EQUD 0
3|%.sparkrootcomm EQUS sparkdel$
3� ALIGN
3�]
3�� debug% �
3�[OPT A%
3�; Start of debugging code
3�
3�.showhandles
3�
3�G; On entry, R2/R3 = Window/icon handles (from GetPointerInfo)
3�
3�) STMFD R13!,{R0,R14}
3�? SWI XOS_WriteI+4 ; � 4 for fast text
3�F SWI XOS_WriteI+30 ; � 30 to keep in top left
4C MOV R0,R2 ; Display window handle
4" BL outhex
4> SWI "XOS_NewLine" ; Next line. I-166
4&A MOV R0,R3 ; Display icon handle
40" BL outhex
4:E SWI XOS_WriteI+5 ; Back to slow text again
4D( LDMFD R13!,{R0,PC}
4N
4X.outhex
4b
4l>; On entry, R0 = Value to printed as 8 hex digits
4v
4�, STMFD R13!,{R0-R2,R14}
4�K ADR R1,hexbuffer ; Convert R0 into 8 zero-padded
4�; MOV R2,#9 ; hex digits...
4�6 SWI "XOS_ConvertHex8" ; II-601
4�C MOV R1,#8 ; ...and print them out
4�3 SWI "XOS_WriteN" ; I-189
4�+ LDMFD R13!,{R0-R2,PC}
4�$.hexbuffer EQUS �12,bl$)
4�
4�; End of debugging code
4�]
4��
4�[OPT A%
5,.checkforred STMFD R13!,{R0,R2,R14}
5? LDRB R0,modifiedbord ; If border is red,
5! MOVS R0,R0
5 J LDRNE R0,curbordercol ; then restore to its previous
5*4 MOVNE R2,#0 ; colour
54) BLNE restoreborder
5>+ LDMFD R13!,{R0,R2,PC}
5H
5R,.turnborderred STMFD R13!,{R0,R1,R14}
5\A LDRB R0,modifiedbord ; Skip if already red
5f! MOVS R0,R0
5p) BNE alreadycooked
5zH ADR R1,wimppalette ; Simply read all 16 colours
5�I SWI "XWimp_ReadPalette" ; and save them. III-1251
5�I LDR R0,[R1,#64] ; Read and save border colour
5�+ STR R0,curbordercol
5�? MOV R0,#&00F000 ; Red in RGB values
5�> MOV R2,#1 ; Flag as modified
5�I BL restoreborder ; Change border colour to red
5�+.alreadycooked LDMFD R13!,{R0,R1,PC}
5�.curbordercol EQUD 0
5�$.wimppalette EQUS �80,bl$)
5�.modifiedbord EQUB 0
5� ALIGN
5�
5�.restoreborder
6
62; On entry, R0 = RGB value for border
6+; R2 = Modified flag
6$
6.) STMFD R13!,{R1,R14}
68+ STRB R2,modifiedbord
6B* ADR R1,wimppalette
6LA STR R0,[R1,#64] ; Store border colour
6V? BL videosync ; Smooth out change
6`L SWI "XWimp_SetPalette" ; Mod border colour. III-1250
6j( LDMFD R13!,{R1,PC}
6t
6~.copyhelpmess
6�
6�7; On entry, R0 = Source address of message
6�5; R2 = Dest address of message
6�2; On exit, R2 = Updated dest address
6�
6�, STMFD R13!,{R0,R1,R14}
6�A.suckuphelp LDRB R1,[R0],#1 ; Copy help text into
6�! MOVS R1,R1
6�< STRNEB R1,[R2],#1 ; message packet
6�& BNE suckuphelp
6�+ LDMFD R13!,{R0,R1,PC}
6�
7 .askedforhelp
7
78; On entry, R1 = Pointer to Wimp_Poll block
7<; R4 = 0 if icon, <> 0 if Info Window
7(
72, STMFD R13!,{R0-R3,R14}
7<J ADD R2,R1,#20 ; Where the help text is to go
7FM MOVS R4,R4 ; Is it the icon or Info window ?
7P' BEQ itsiconhelp
7Z> ADR R0,helpmessinfo ; Info Window help
7d( BL copyhelpmess
7n) B finishmessnow
7xI.itsiconhelp ADR R0,helpmessicon ; First help line is constant
7�( BL copyhelpmess
7�J LDRB R3,CMOSbyte ; Now decide on Immediate text
7�? TST R3,#%001 ; or Trash$Dir info
7�( ADRNE R0,helpimmed
7�( ADREQ R0,helpstore
7�( BL copyhelpmess
7�I TST R3,#%010 ; Add Warning text if enabled
7�' ADRNE R0,helpwarn
7�( BLNE copyhelpmess
7�K TST R3,#%100 ; Add Animation text if enabled
7�' ADRNE R0,helpanim
7�( BLNE copyhelpmess
7�D.finishmessnow MOV R0,#0 ; Null terminator needed
8' STRB R0,[R2,#-2]
8L ADD R0,R2,#2 ; Compute word-rounded length of
8; BIC R0,R0,#%11 ; message block
8"$ SUB R0,R0,R1
8,B STR R0,[R1] ; Save length in block
86E LDR R2,[R1,#4] ; Task handle to reply to
8@C LDR R0,[R1,#8] ; Copy reference number
8J' STR R0,[R1,#12]
8T$ MOV R0,#&500
8^C ADD R0,R0,#3 ; !Help reply ID = &503
8h' STR R0,[R1,#16]
8r" MOV R0,#17
8|/ SWI "XWimp_SendMessage"
8�+ LDMFD R13!,{R0-R3,PC}
8��.helpmessinfo EQUS "This is the Info Window.|MIt shows the name and purpose of this application as well as the author, "
8�_ EQUS "version number and date developed. It employs 'auto-stamping' to "
8�d EQUS "synchronise "+prog$+" module and Info Window versions and dates.|M"+bl$
8� ALIGN
8�T.helpmessicon EQUS "This is the "+prog$+" icon. Drag files onto it to "+bl$
8� ALIGN
8�T.helpimmed EQUS "delete them immediately.|MMENU: Toggles options.|M"+bl$
8� ALIGN
8�.helpstore EQUS "put them in the "+prog$+".|MMENU: Toggles options/empties trash. SELECT or ADJUST: View trash.|M"+bl$
8� ALIGN
8�R.helpwarn EQUS "A red border warning is shown before deletion.|M"+bl$
8� ALIGN
9G.helpanim EQUS "A Trash Van will pick up the trash.|M"+bl$
9 ALIGN
9
9&,.videosync STMFD R13!,{R0-R2,R14}
90H MOV R0,#19 ; È– (watch out - annoyingly
9:J SWI "XOS_Byte" ; corrupts R1 and R2 !). I-298
9D+ LDMFD R13!,{R0-R2,PC}
9N
9X.wimpspriteop
9b
9l5; On entry, R0 = OS_SpriteOp reason code
9vB; R2 = Pointer to sprite name (or filename)
9�6; R3.. = Other OS_SpriteOp params
9�
9�, STMFD R13!,{R0-R2,R14}
9�
9�J; Note to Acorn - I would DEARLY like to use Wimp_SpriteOp exclusively
9�E; in this module, but it doesn't support any "write" operations !
9�
9�K ADD R0,R0,#&100 ; Pointing to special user area
9�6 SWI "XWimp_SpriteOp"; III-1271
9�+.leavespriteop LDMFD R13!,{R0-R2,PC}
9�
9�
.spriteop
9�
:5; On entry, R0 = OS_SpriteOp reason code
:B; R2 = Pointer to sprite name (or filename)
:6; R3.. = Other OS_SpriteOp params
:
:*, STMFD R13!,{R0-R2,R14}
:4< ADD R0,R0,#&100 ; Flag user area
:>) LDR R1,spritearea
:H3 SWI "XOS_SpriteOp" ; I-393
:R+ LDMFD R13!,{R0-R2,PC}
:\
:f.trundlevan
:p
:z;; On entry, R0 = Pointer to sprite family name
:�,; R1 = Start position
:�-; R2 = Finish position
:�I; R3 = OS units between each movement (can be -ve)
:�'; R7/R8 = X/Y shift
:�
:�- STMFD R13!,{R0-R10,R14}
:�( STMFD R13!,{R0-R3}
:�! MOV R2,R0
:�? MOV R9,#�"1" ; Select first sprite
:�& STRB R9,[R2,#6]
:�> MOV R0,#40 ; Read sprite info
:�3 BL wimpspriteop ; I-423
:�B BVS spritefailure ; Give up if no sprite
;K MOV R5,#1 ; Bottom of van = 1 pixel above
;F MOV R5,R5,ASL R8 ; screen bottom (scale it)
;A SUBS R3,R3,#1 ; Width of sprite - 1
;$B BMI spritefailure ; Give up if width = 0
;.J MOV R7,R3,ASL R7 ; then shift it by the Xfactor
;8B SUBS R4,R4,#1 ; Height of sprite - 1
;BC BMI spritefailure ; Give up if height = 0
;LJ MOV R8,R4,ASL R8 ; then shift it by the Yfactor
;V( LDMFD R13!,{R0-R3}
;`G BL saveundervan ; Initial temp sprite setup
;j( BVS vanhitfinish
;t
;~H; The rest of this routine deals with moving the van (smoothly !) in
;�F; a straight horizontal line between R1 and R2 (step R3). It flips
;�9; between 3 different sprites every third video sync.
;�
;�@.animationflip MOV R10,#3 ; Reset flip counter
;�; STRB R9,[R0,#6] ; Select sprite
;�B.noanimflip BL videosync ; Smooth out animation
;�D ADR R4,tempoutsprite; Select saved rectangle
;�> MOV R6,#0 ; Overwrite screen
;�J BL plotsprite ; Restore underneath rectangle
;�( BVS vanhitfinish
;�= ADD R1,R1,R3 ; Move van xcoord
;�J MOVS R3,R3 ; Which way is the van going ?
<