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 ? <