; Copyright 1996 Acorn Computers Ltd ; ; Licensed under the Apache License, Version 2.0 (the "License"); ; you may not use this file except in compliance with the License. ; You may obtain a copy of the License at ; ; http://www.apache.org/licenses/LICENSE-2.0 ; ; Unless required by applicable law or agreed to in writing, software ; distributed under the License is distributed on an "AS IS" BASIS, ; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ; See the License for the specific language governing permissions and ; limitations under the License. ; ; > Sources.Wimp02 ;;----------------------------------------------------------------------------- ;; Initialise current task - allocate block from RMA if necessary ;; In R0 = latest Wimp version known to this task (0 => old-style task) ;; For swapping versions: ;; If R0 > swapping_version: ;; R3 -> List of message numbers the task understands terminated ;; by a zero word (task must always understand message 0 = Quit !) ;; ;;----------------------------------------------------------------------------- markinitialised Push "R0-R4,LR" ; LDR R4,taskhandle LDR R2,[wsptr,R4] TST R2,#task_unused ; in practice task cannot be used! BEQ %FT01 ; (Wimp_Init calls closedown first) ; LDR R2,pendingtask ; see if we can grab this one! CMP R2,#0 MOVPL R14,#nullptr STRPL R14,pendingtask BPL %FT02 ; Push "R3" MOV R3,#task_datasize BL claimblock Pull "R3" BVS %FT99 ; MOV R14,#nullptr ; null slot if new task STR R14,[R2,#task_slotptr] MOV R14,#0 ; no fp registers saved STR R14,[R2,#task_fpblock] STR R14,[R2,#task_windows] STR R14,[R2,#task_messagessize] STR R14,[R2,#task_vfpcontext] MOV R14,#-1 STR R14,[R2,#task_messages] ; flag as accepting all messages 02 Debug task1,"Task block allocated:",R4,R2,wsptr STR R2,[wsptr,R4] LDR R14,taskcount ; if task wasn't already initialised ADD R14,R14,#1 ; increment task count STR R14,taskcount Debug task1,"tastcount",#taskcount 01 Debug task1,"task pointer, handle =",R2,R4 LDR R0,[sp] ; latest known Wimp version STR R0,[R2,#task_wimpver] ; separate copy for each task ; The following things are held for each task ready for swapping to be enabled. Debug task1,"task count =",#taskcount Debug task1,"about to add messages to list" LDR R14,=284 ; R4 = task handle from above. CMP R0,R14 MOVHS R14,#0 MOVLO R14,#priority_old ; if old style task then flag as old priorty STR R14,[R2,#task_priority] Debug task1,"task_priority =",R14 BLO %FT01 ; ignore the messages if not a valid task CMP R3,R3,ASR #31 ; is the handle valid? (-1 pointer still means all messages, for compatibility) MOVEQ R14,R3 ; set all or no messages MOVNE R14,#0 ; set no messages prior to calling addmessages STR R14,[R2,#task_messages] BEQ %FT01 BL addmessages ; add messages as required LDR R14,[R2,#task_messages] TEQ R14,#0 ; if still no messages MOVEQ R14,#-1 STREQ R14,[R2,#task_messages] ; then they actually wanted all of them 01 [ Swapping ; Things to be done only if swapping is enabled. ADRL R1,swapping LDR R3,[R1] CMP R3,#0 MOVEQ R14,R3 BEQ %FT02 ; No swap$dir ADRL R0,swap_filename LDR R14,[R0] Push "R14" BL increment_swap_filename Pull "R14" 02 MOV R0,#0 STR R14,[R2,#task_filename] ; Store name even if error. STR R0,[R2,#task_file] ; 0 if error. ] LDR R14,tasknumber ; global counter ADD R14,R14,#flag_version ; increment version number (always) BICS R14,R14,#task_unused ; ensure top bit unset ADDEQ R14,R14,#flag_version ; avoid 0! STR R14,tasknumber STR R14,[R2,#task_flagword] Debug task1,"tasknumber =",R14 99 Debug task1,"back from markinitialised" STRVS R0,[sp] Pull "R0-R4,PC" ; ; Entry: if R1 = "TASK", then ; R0 = latest known Wimp version number * 100 ; (If known version >= 284) R3 -> List of messages the task wants to receive. ; Exit: R0 = actual Wimp version number * 100 ; if R1 = "TASK" on entry, then ; R1 = task handle on exit ; ; In future Wimps, the value of R0 on entry to Wimp_Initialise will be used ; to get round any compatibility issues ; wn_command DCB "command",0 ALIGN wn_error DCB "error",0 ; must be word-aligned ALIGN wn_backwindow DCB "backwindow",0 ALIGN [ Swapping swap_var_name DCB "Swap$Dir",0 ALIGN swap_limit_name DCB "Swap$Limit",0 ALIGN ] svc_closedown * 0 svc_initialise * 1 SWIWimp_Initialise MyEntry "Initialise" Debuga xx,"Wimp_Initialise: R0 =",R0 Debug xx,", taskcount =",#taskcount Push "R0-R3" LDR R14,commandflag ; watch out for errors later! ORR R14,R14,#cf_suspended ; NB this stops closedown from STR R14,commandflag ; setting the command window pending MOV R1,#0 ; ensure R1 <> "TASK" MOV R2,#svc_initialise BL closedown ; close down previous task in domain STRVS R0,[sp] Pull "R0-R3" ; error can be returned from this! BVS exitinit ; un-suspends command window ; Debug xx,"taskcount =",#taskcount ; LDR R14,taskcount ; if more tasks running, ensure that TEQ R14,#0 ; quit handler has not been set up BEQ initfirsttask ; Debug xx,"taskcount (after) =",#taskcount ; LDR R14,parentquithandler ; check for nasty tasks like Twin ; ADRL R3,Do_ExitHandler ; TEQ R14,R3 ; can't allow them to set exit handlers ; XError WimpCantKill,NE ; no => "Wimp is currently active" ; Debug xx,"Version requested =",R0 ; BLVC checkversion ; refuse to start up if bad version BLVC markinitialised ; increase 'task version number' ADRVCL R3,tempiconblk ; set up key codes BLVC resetkeycodes ; (but don't remember old settings) Debug task1,"New task:",#taskhandle ; B rationalisememory [ true ; debug taskidentifier2 DCB "TASK" ] ; ; if error window doesn't exist, read it in (before error handler set!) ; initfirsttask Push "R0-R3" [ AutoHourglass MOV R0, #0 STR R0, hourglass_status ; note that autohourglass is initially switched off ] ; [ SwitchingToSprite MOV R0, #0 STR R0, switchtospr_current ; initialise both of these as though output is directed to screen STR R0, switchtospr_correctfor ] ; [ true LDR R0,currentmode CMP R0,#-1 ; MOVNE R1,#0 ; STRNE R1,currentmode BEQ %FT02 ; BL int_setmode ; MOV R1,#1 ; ADRL R14,wimpmodebefore ; STRB R1,[R14] B %FT05 02 ] MOV R0,#1 ; Read configured mode SWI XOS_ReadSysInfo BLVC validatemode ; error if non-graphics mode MOVVS R0,#27 [ Medusa BL copy_mode_specifier ] STR R0,currentmode ; altered by Wimp_SetMode 05 BL recalcmodevars ; before any SWIs are called! BL getromsprites ; LDR R0,tool_area ; have any tools be pre-loaded? TEQ R0,#0 BLEQ int_toolsprites ; none already installed so load some new ones CLRV ; ignore errors - falls back as required ; [ :LNOT: Swapping Pull "R0-R3" ] ; [ Swapping ADR R0,swap_var_name ADRL R1,swap_path MOV R2,#-1 MOV R3,#0 MOV R4,#3 SWI XOS_ReadVarVal TEQ R2,#0 ADREQL R0,swapping STREQ R2,[R0] BEQ %FT02 ; No swap directory. ADR R0,swap_var_name ADRL R1,swap_path MOV R2,#256 MOV R3,#0 MOV R4,#3 SWI XOS_ReadVarVal BVS exitinit MOV R0,#"." ; Add a "." to the string. STRB R0,[R1,R2] ADD R2,R2,#1 ADRL R0,swapping STR R2,[R0] ADRL R0,swap_filename LDR R1,=&00414141 STR R1,[R0] ADR R0,swap_limit_name ; Get limit of swap space. ADRL R1,errorbuffer MOV R2,#-1 MOV R3,#0 MOV R4,#3 SWI XOS_ReadVarVal TEQ R2,#0 BEQ %FT02 ; No limit. ADR R0,swap_limit_name ; Get limit of swap space. ADRL R1,errorbuffer MOV R2,#256 MOV R3,#0 MOV R4,#3 SWI XOS_ReadVarVal BVS exitinit MOV R0,#10 ; Read number in base 10. SWI XOS_ReadUnsigned BVS exitinit LDRB R0,[R1] ; Get terminator. ORR R0,R0,#32 ; Make Lowercase TEQ R0,#"m" MOVEQ R2,R2,ASL #20 ; Convert to bytes. TEQ R0,#"k" MOVEQ R2,R2,ASL #10 ; Convert to bytes. 02 ADRL R0,swapsize STR R2,[R0] Debug swp,"Swap size is ",R2 MOV R0,#0 ADRL R2,swapused STR R0,[R2] Pull "R0-R3" ] MOV R14,#bignum STR R14,lastmode_x1 ; force onto screen first time STR R14,lastmode_y1 BL checkversion ; refuse to start up if bad version BLVC markinitialised ; increase 'task version number' BVS exitinit Debug task1,"First task:",#taskhandle ; MOV R0,#-1 SWI XTerritory_WriteDirection MOVVS R0,#WriteDirection_LeftToRight TST R0,#WriteDirection_RightToLeft MOVNE R0,#-1 MOVEQ R0,#0 STR R0,writeabledir MOVNE R0,#0 STR R0,reversedmenu STR R0,externalcreate ; STR R0,old_icon STR R0,old_window STR R0,special_pointer ; STR R0,IdlePerSec MOV R0,#-32 STR R0,MaxIdleEvents ; setup ready for speed monitoring ; Push "R0-R2" [ Stork SWI XPortable_ReadFeatures BVC %FT01 ; MOV R0, #0 MOV R1, #0 SWI XPortable_Speed ; attempt to make the portable go fast! MOVVC R1, #PortableFeature_Speed MOVVS R1, #0 01 AND R1, R1, #(PortableFeature_Speed :OR: PortableFeature_Idle :OR: PortableFeature_Stop) TST R1, #(PortableFeature_Speed :OR: PortableFeature_Idle) STR R1, WimpPortableFlags BEQ %FT01 ; don't attach call back routine if no portable | MOV R0,#0 MOV R1,#0 SWI XPortable_Speed ; attempt to make the portable go fast! MOVVC R0,#-1 MOVVS R0,# 0 ; flag to indicate presence of portable module STR R0,WimpPortableFlag BVS %FT01 ; don't attach call back routine if no portable ] ; MOV R0,#99 ; call every second (99 due to bug in CallEvery) ADRL R1,CallEveryHandler MOV R2,WsPtr SWI XOS_CallEvery ; install handler 01 [ mousecache MOV R0,#TickerV ADRL R1,MouseCallEveryHandler BL claim ; MOV R0,#-1 ; recache when required STRB R0,recacheposn ] [ NewErrorSystem [ WatchdogTimer MOV R0,#9 ; ten times a second ADRL R1,BreakWatchdogHandler STR R1,watchdogarea MOV R2,WsPtr SWI XOS_CallEvery | MOV R0,#EventV ADRL R1,BreakWatchdogHandler MOV R2,WsPtr SWI XOS_Claim MOV R0,#14 MOV R1,#Event_Keyboard SWI XOS_Byte ] ] ; [ outlinefont BL FindFont ; recache the system font (if possible!) ] ; CLRV Pull "R0-R2" ; LDR R0,backwindowhandle CMP R0,#nullptr BNE %FT01 ADR R0,wn_backwindow MOV R2,#0 MOV R3,#0 BL createsystemp STRVC R0,backwindowhandle MOVVC R1,#nullptr2 ; open at back BLVC openfullsize ; open at full size of screen BVS exitinit ; LDR R0,errorhandle CMP R0,#nullptr BNE %FT01 ADR R0,wn_error ADRL R2,errortitle ; indirected icons go in [errortitle] ADRL R3,errortitend ; (assume title is first icon) BL createsystemp STRVC R0,errorhandle BVS exitinit ; [ NewErrorSystem LDR R14, [handle, #w_icons] ; read important values from the template before they get corrupted ADD R3, R14, #i_size * 1 ; use Continue button as template for default (aka "highligted") buttons LDR R2, [R3, #i_bby0] STR R2, errbut_y0_def LDR R2, [R3, #i_bby1] STR R2, errbut_y1_def LDR R2, [R3, #i_flags] BIC R2, R2, #is_inverted :OR: is_deleted STR R2, errbut_fl_def LDR R2, [R3, #i_data + 4] STR R2, errbut_va_def LDR R2, [R3, #i_bbx0] LDR R3, [R3, #i_bbx1] SUB R2, R3, R2 STR R2, errbut_w_def ADD R3, R14, #i_size * 4 ; use Cancel button as template for other buttons LDR R2, [R3, #i_bby0] STR R2, errbut_y0 LDR R2, [R3, #i_bby1] STR R2, errbut_y1 LDR R2, [R3, #i_flags] BIC R2, R2, #is_inverted :OR: is_deleted STR R2, errbut_fl LDR R2, [R3, #i_data + 4] STR R2, errbut_va LDR R2, [R3, #i_bbx0] LDR R3, [R3, #i_bbx1] SUB R2, R3, R2 STR R2, errbut_w LDR R2, [R14, #i_size * 2 + i_bbx0] ; remember distance app sprite is in from the side STR R2, errapp_x0 LDR R2, [R14, #i_size * 3 + i_bbx0] ; remember distance error type sprite is in from the side STR R2, errtype_x0 LDR R2, [R14, #i_size * 0 + i_bbx0] ; remember distance error message is in from the side STR R2, errmess_x0 | LDR R14,[handle,#w_icons] LDR R14,[R14,#1*i_size+i_flags] ; OK box AND R14,R14,#if_fcol:OR:if_bcol STR R14,highlighted_colour LDR R14,[handle,#w_icons] LDR R14, [R14, #4*i_size+i_flags] ; Cancel box AND R14,R14,#if_fcol:OR:if_bcol STR R14,unhighlighted_colour ] 01 LDR R0,commandhandle CMP R0,#nullptr BNE %FT01 ; ADRL R0,wn_command ; for *Copy etc. MOV R2,#0 MOV R3,#0 BL createsystemp STRVC R0,commandhandle BVS exitinit ; can't cope without this! 01 ; ; if first task, replace its quit handler with mine, and remember old one! ; Debug task1,"Setting up handlers for first task" ; MOV R0,#ExitHandler ADRL R1,Do_ExitHandler MOV R2,wsptr ADRL R3,registerbuffer SWI XOS_ChangeEnvironment BVS exitinit ; ADRL R14,Do_ExitHandler TEQ R1,R14 ; Is this my own quit handler??? BEQ skipupcall ; if same, we've done this already! ; ADR R14,wimpquithandler STMIA R14,{R1-R3} ; MOV R0,#UpCallV ; claim upcall at same time ADRL R1,UpCallCode BL claim ; SWI XOS_ReadMonotonicTime ; reset the counter STR R0,rotatecounter skipupcall BL setdefaulthandlers ; looks at [handlerword] BL findpages ; initialise free pool, if possible BVS exitinit ; DO THIS FIRST - MEMORY MAY MOVE!!! ; ADR R3,oldfxstatus ; remember old codes BL resetkeycodes ; *FX 4,2 etc. ; [ true ; debug LDR R5,taskidentifier2 ; if R1="TASK" on entry ... | LDR R5,taskidentifier ; if R1="TASK" on entry ... ] TEQ userblk,R5 BEQ %FT02 ; BL int_allbutmode ; don't set mode/palette if old type ADRL R1,paltable MOV R2,#15 01 STRB R2,[R1,R2,LSL #2] ; set up 1:1 mapping SUBS R2,R2,#1 BPL %BT01 02 ; deallocate application memory if it isn't being used rationalisememory Debug task1,"into rationalisememory" [ :LNOT:Medusa LDR R14,freepool ;; Wimp 1.89o onwards CMP R14,#nullptr ;; don't bother if no free pool BEQ %FT01 ;; (keep all the memory) ] BLVC testapplication ; unless application space is in use, BCC %FT01 Debug task1,"Application space being used" [ Swapping ; No need for swap file if no Push "R0" ; application memory. LDR R14,taskhandle LDR R14,[wsptr,R14] MOV R0,#0 STR R0,[R14,#task_filename] Pull "R0" ] BLVC deallocateslot ; reclaim the memory MOVVC R1,#ApplicationStart BLVC setmemsize ; rewrite memory limit as well! 01 DebugE task1,"exitinit with " BVS exitinit ; MOV R14,#nullptr ; can't call this while redrawing! STR R14,redrawhandle STR R14,backwindow ; assume none yet ; Debug task1,"singletaskhandle",#singletaskhandle ; LDR R14,singletaskhandle CMP R14,#nullptr BEQ returntaskhandle ; ; if old-style Wimp_Init, cover any pre-existing windows ; Debug task1,"Single-tasking" ; ADR userblk,backdef-(w_flags-w_cw0) BL int_create_window STRVC R0,backwindow ; R0 = relative handle (remember) MOVVC R1,#nullptr ; R1 = bhandle (open at front) BLVC openfullsize ; B exitinit ;.............................................................................. ; Ticker routine called every second if its a portable, install a callback ; handler and then exit. CallEveryHandler Entry "R0-R1" [ No32bitCode MOV R0,PC TEQP PC,#SVC_mode ; back to SVC mode IRQs on NOP | MRS R0,CPSR BIC R1,R0,#I32_bit+F32_bit ORR R1,R1,#SVC_mode MSR CPSR_c,R1 ] Push "R0,LR" ; preserve SVC_R0 and SVC_R14 ADR R0,callback MOV R1,WsPtr ; -> callback routine SWI XOS_AddCallBack Pull "R0,LR" [ No32bitCode TEQP PC,R0 ; back to original mode NOP | MSR CPSR_c,R0 ] Pull "R0-R1,PC" ; and then back to original handler ;.............................................................................. ; This ticker gets called every 50hz, it is called to allow the mouse ; co-ordinates to be re-read at a suitable point so that we do not ; continually poll the Window Manager. [ mousecache MouseCallEveryHandler MOV R0,#-1 ; flag as needing to re-read mouse posn STRB R0,recacheposn MOV PC,LR ] ;.............................................................................. ; CallBack routine used to update the idle speeds ready for speed control. ; 321nk updated to use PowerUtils 'more inteligent' algorithms. callback Entry "R0-R3" LDR r3, IdlePerSec MOV r1, #0 ; read and then reset, even if not active STR r1, IdlePerSec LDR r0, taskcount TEQ r0, #0 ; r0=0 => Wimp inactive LDRNE r0, commandflag EORNES r0, r0, #cf_active ; r0=0 => command window active EXIT EQ ; not active, so don't mess around with speed LDR r1, MaxIdleEvents ; get the maximum read so far CMP r1, #0 ADDLT r1, r1, #1 STRLT r1, MaxIdleEvents ; hmmm? STRLT r1, MaxSlowIdleEvents STRLT r1, MaxFastIdleEvents EXIT LT ; return if LT 0! [ Stork ;DREG r3, "Idle count: ",cc,Integer LDR r0, MaxSlowIdleEvents ;DREG r0, " Slow count: ",cc,Integer LDR r0, MaxFastIdleEvents ;DREG r0, " Fast count: ",,Integer LDR r2, WimpPortableFlags TST r2, #PowerSave ; are we in power save mode BNE %FT10 | MOV r0, #0 ; read old state MOV r1, #-1 SWI XPortable_Speed ; r0 = old state EXIT VS ; if an error, don't do anything stupid TEQ r0, #0 BNE %FT10 ] ; was going fast LDR r0, MaxFastIdleEvents Debug xx,"r3 = ",r3 SUBS r0, r0, r0, LSR #5 ; multiply by 31/32 to do decay STREQ r3, MaxFastIdleEvents ; if we haven't had any yet, then store new max EXIT EQ ; and exit CMP r3, r0 MOVGT r0, r3 STR r0, MaxFastIdleEvents MOV r1, r0, LSR #3 ADD r1, r1, r1, LSR #1 SUB r0, r0, r1 ; r0 = 13/16 of maximum CMP r3, r0 CMPGT r3, #Threshold ; If below threshold, never go slow. [ Stork [ PokeBorder VIDC EQU &03500000 LDRGT r2, =&40FF00FF ; magenta = slow LDRLE r2, =&40FFFF00 ; cyan = fast MOV r0, #VIDC STR r2, [r0] LDR r2, WimpPortableFlags ; restore corrupted r2 ] EXIT LE ; exit if we want to go fast cos we're already doing so ORR r2, r2, #PowerSave ; indicate power save mode STR r2, WimpPortableFlags TST r2, #PortableFeature_Speed ; if speed change works MOVNE r0, #1 MOVNE r1, #0 SWINE XPortable_Speed ; then issue SWI 'go slow' ; else we call Portable_Idle elsewhere | [ PokeBorder LDRGT r2, =&4000080F ; magenta = slow LDRLE r2, =&400008F0 ; cyan = fast ] MOVGT r0, #1 ; if we want to go slow, then issue SWI MOVGT r1, #0 SWIGT XPortable_Speed [ PokeBorder VIDC * &03400000 MOV r0, #VIDC STR r2, [r0] ] ] EXIT ; was going slow 10 LDR r0, MaxSlowIdleEvents SUB r0, r0, r0, LSR #5 ; multiply by 31/32 to do decay CMP r3, r0 MOVGT r0, r3 STR r0, MaxSlowIdleEvents MOV r0, r0, LSR #1 ; r0 = 1/2 of maximum CMP r3, r0 [ Stork [ PokeBorder LDRGT r2, =&40FF00FF ; magenta = slow LDRLE r2, =&40FFFF00 ; cyan = fast MOV r0, #VIDC STR r2, [r0] LDR r2, WimpPortableFlags ; restore corrupted r2 ] EXIT GT ; exit if we want to go slow cos we're already doing so BIC r2, r2, #PowerSave ; full steam ahead STR r2, WimpPortableFlags TST r2, #PortableFeature_Speed ; if speed change works MOVNE r0, #0 MOVNE r1, #0 SWINE XPortable_Speed ; then issue SWI 'go fast' | [ PokeBorder LDRGT r2, =&4000080F ; magenta = slow LDRLE r2, =&400008F0 ; cyan = fast ] MOVLE r0, #0 ; if we want to go fast, then issue SWI MOVLE r1, #0 SWILE XPortable_Speed [ PokeBorder MOV r0, #VIDC STR r2, [r0] ] ] EXIT ;.............................................................................. ; In R0 = window handle ; R1 = bhandle (-1 for front, -2 for back) ; Out window opened at full size of screen openfullsize Push "cx0-y1,userblk,LR" ; ADRVC R14,scrx0 LDMVCIA R14,{cx0,cy0,cx1,cy1} ; dimensions of screen MOVVC x0,#0 ; scroll x,y MOVVC y0,#0 ; Push "R1" ; bhandle Push "R0,cx0,cy0,cx1,cy1,x0,y0" ; handle,x0,y0,x1,y1,scx,scy MOVVC userblk,sp BLVC int_open_window ADD sp,sp,#u_ow1 ; Pull "cx0-y1,userblk,PC" ;.............................................................................. ; In R3 -> save area for old key settings ; Out *fx 4,2 : *fx 219,&8A : *fx 221,2 .. 228,2 : *fx 229,1 : *fx 124 ; *fx 9,0 : *fx 10,0 resetkeycodes Push "LR" ; Debug task1,"setting up key codes: R12,R13,R3 =",R12,R13,R3 ; MOV R0,#4 MOV R1,#2 SWI XOS_Byte ; *FX 4,2 STRB R1,[R3],#1 ; MOV R0,#219 MOV R1,#&8A ; *FX 219,&8A (TAB key) MOV R2,#0 SWI XOS_Byte STRB R1,[R3],#1 ; MOV R0,#221 01 Push "R0" MOV R1,#2 MOV R2,#0 SWI XOS_Byte ; *FX 221,2 to *FX 228,2 Pull "R0" STRB R1,[R3],#1 ADD R0,R0,#1 CMP R0,#228 BLS %BT01 ; MOV R0,#9 MOV R1,#0 SWI XOS_Byte STRB R1,[R3],#1 MOV R0,#10 MOV R1,#0 SWI XOS_Byte STRB R1,[R3],#1 ; LDR R14,singletaskhandle CMP R14,#nullptr ; old Wimp didn't set up escape! BNE noescape ; NB old tasks can't start others! ; MOV R0,#229 ; *FX 229,1 (escape ==> ascii 27) MOV R1,#1 MOV R2,#0 SWI XOS_Byte STRB R1,[R3],#1 ; MOV R0,#124 ; clear escape condition (if any) SWI XOS_Byte noescape Debug task1,"key codes reset" CLRV Pull "PC" ; ignore errors backdef DCD wf_autoredraw:OR:wf_nochecks:OR:wf_backwindow DCB 0,0,0,4, 0,0,0,0 DCD 0,-bignum,bignum,0 DCD 0 ; title flags DCD ibt_never:SHL:ib_buttontype ; work area flags DCD 0 ; areaCBptr DCD 0 ; reserved DCD 0,0,0 ; title DCD 0 ; no of icons endbackdef ASSERT (endbackdef-backdef) = (w_cw1-w_flags) ;.............................................................................. ; if R1 = "TASK" on entry, return R1 = task handle on exit ; send TaskInitialise broadcast as well returntaskhandle BL fulltaskhandle ; R14 = handle including version bits STR R14,[sp,#0*4] ; overwrite value of R1 on stack ; MOV R0,#MemoryLimit ; do this now cos R0 needed MOV R1,#0 SWI XOS_ChangeEnvironment SUB R5,R1,#ApplicationStart ; data + 4 ; LDR R0,[sp,#1*4] ; send message including name BL count0 ; R1 = length of string (inc. 0) ADD R1,R1,#3 BIC R1,R1,#3 ; align to word boundary ADD R1,R1,#ms_data+8 STR R1,[sp,-R1]! ; set up message block on stack ; [ debugxx ADD R1,sp,R1 LDMIA R1,{R1,R2} Debuga xx,", handle =",R1 DebugS xx,", name =",R2 ] ; BL readCAOpointer ; R2 = CAO pointer MOV R4,R2 MOV R2,#0 ; your ref LDR R3,=Message_TaskInitialise ; action ; ADD R1,sp,#ms_yourref ; R5 set up earlier! STMIA R1!,{R2-R5} LDRB R14,[R0] TEQ R14,#"\\" ADDEQ R0,R0,#1 BL copy0 ; copy from [R0] to [R1] ; MOV R0,#User_Message MOV R1,sp MOV R2,#0 ; broadcast BL int_sendmessage ; send from this task LDR R14,[sp] ADD sp,sp,R14 ; correct stack BVS exitinit ; LDR R14,commandflag TEQ R14,#cf_pending:OR:cf_suspended LDRNE R0,currentmode ; reset mode if nasties have occurred ; ADRNEL R14,wimpmodebefore ; LDRNEB R14,[R14] ; TEQNE R14,#1 ; mode already changed BLNE int_setmode ; command window suspended, so it's OK exitinit Debug task1,"exitinit; command flag =",#commandflag LDR R14,commandflag ; un-suspend window, BIC R14,R14,#cf_suspended STR R14,commandflag MOVVC R0,#-1 ; then get rid of it if no errors! SWIVC XWimp_CommandWindow ; LDRVC R0,=Module_Version ; R0 = Wimp version number B ExitWimp LTORG ;.............................................................................. ; In R1 = "TASK" => R0 = latest known Wimp version ; otherwise this is an old-style task ; Out R0 = latest known Wimp version (0 if old-style task) ; [singletaskhandle] = [taskhandle] if old-style task ; [singletaskhandle] = -1 if new-style task ; Error if R1 = "TASK" but R0 looks invalid checkversion Push "LR" LDR R14,taskidentifier2 TEQ R1,R14 MOVEQ R14,#nullptr ; new-style tasks are not single-tasking LDRNE R14,taskhandle STR R14,singletaskhandle MOVNE R0,#0 STRNEB R0,modechanged ; don't deliver if old-style task Pull "PC",NE ; a mode change will occur on exit [ true CMP R0,#200 ; must be AT LEAST version 2.00 BLO %FT01 CMP R0,#300 MOVLO R0,#200 TEQLO R0,R0 ; If 200 <= v < 300 Then v=200 ! BEQ %FT01 [ true [ ChildWindows TEQ R0,#380 LDRNE R0,=310 ; unless v=380, set v=310 | LDR R0,=310 ; IF v>300 Then v=310 ] TEQ R0,R0 | LDR R14,=310 CMP R0,R14 MOVLO R0,R14 ; If 300 < v < 310 Then v=310 TEQLO R0,R0 ; If 200 <= v < 300 Then v=200 ! ] 01 [ true MyXError WimpBadVersion,NE | Push "R0-R3" MyXError WimpBadVersion,NE MOVNE R1,#0 SWINE XWimp_ReportError ; Report the error, but don't return it ! Pull "R0-R3" ] | RSBCSS R14,R0,#10240 ; assume version 102.40 is latest! MyXError WimpBadVersion,CC ] Pull "PC" MakeErrorBlock WimpBadVersion ;.............................................................................. ; Entry: [taskhandle] = task index ; Exit: R14 = full task handle (including version number) fulltaskhandle Push "R1,LR" LDR R1,taskhandle LDR R14,[wsptr,R1] LDR R14,[R14,#task_flagword] MOV R14,R14,LSR #flag_versionbit ORR R14,R1,R14,LSL #flag_versionbit Pull "R1,PC" LTORG ;;------------------------------------------------------------------------------ ;; in R0=0 => print syntax message only ;; R0=1 => *Status WimpMode was typed - print out value ;; R0-> command tail => *Configure WimpMode <mode> ;; out if *configure, CMOS RAM configured ;; [currentmode] or [sysflags] reset ;;----------------------------------------------------------------------------- [ true ; New configuration code that isn't as closely tied to the CMOS byte involved ; (most bytes are now shared by multiple options) MACRO $lab ConfigOption $string, $unit, $cmosbyte, $cmosbit, $cmossize, $shift, $eor, $expbyte, $expbit, $intvar, $intmul, $intbyte, $lut, $num ; $string: tail of label for status string ; $unit: (optional) tail of label for unit token string ; $cmosbyte: byte to read for mantissa ; $cmosbit: (default 0) minimum significant bit ; $cmossize: (default 8) number of significant bits ; $shift: non-null means don't shift mantissa bitfield down when reading (to make lsb=0) ; $eor: (optional) value to EOR with mantissa read from CMOS ; $expbyte: (optional) byte holding 1-bit exponent ; $expbit: (optional) bit holding 1-bit exponent ; $intvar: (optional) internal variable to set to value ; $intmul: non-null means store value * 10 in internal variable ; $intbyte: B => store as byte value ; $lut: (optional) label for table of <8 char strings to use for each value ; $num: non-null means table contains 32-bit words instead Entry "R7-R11" LDR wsptr, [R12] CMP R0, #1 BHI %FT02 BEQ %FT01 ; Print syntax string ADRL R0, configmess_$string SWI XOS_Write0 EXIT ; Print status string 01 ADR R0, statusmess_$string SWI XOS_Write0 MOVVC R0, #ReadCMOS MOVVC R1, #$cmosbyte SWIVC XOS_Byte [ "$expbyte" <> "" :LAND: "$expbit" <> "" [ $expbyte = $cmosbyte MOVVC R4, R2 ; remember, to save another CMOS read later ] ] [ "$cmosbit" <> "" :LAND: "$cmossize" <> "" ANDVC R2, R2, #((1 :SHL: $cmossize) - 1) :SHL: $cmosbit [ "$shift" = "" :LAND: $cmosbit <> 0 MOVVC R2, R2, LSR#$cmosbit ] ] [ "$eor" <> "" [ $eor <> 0 EORVC R2, R2, #$eor ] ] [ "$expbyte" <> "" :LAND: "$expbit" <> "" MOVVC R3, R2 [ $expbyte = $cmosbyte MOVVC R2, R4 ; get value read earlier | MOVVC R0, #ReadCMOS MOVVC R1, #$expbyte SWIVC XOS_Byte ] TSTVC R2, #1 :SHL: $expbit ; preserves V ADDNE R3, R3, R3, LSL#2 MOVNE R2, R3, LSL#1 ; multiply by 10 MOVEQ R2, R3 ] [ "$lut" = "" SUB sp, sp, #4 ; buffer space MOVVC R0, R2 MOVVC R1, sp MOVVC R2, #4 SWIVC XOS_ConvertCardinal1 SWIVC XOS_Write0 ADD sp, sp, #4 | ADRVCL R0, $lut [ "$num" = "" ADDVC R0, R0, R2, LSL#3 ; strings are at 8-byte intervals SWIVC XOS_Write0 | ADDVC R0, R0, R2, LSL#2 ; ints are at 4-byte intervals SUB sp, sp, #12 ; buffer space LDRVC R0, [R0] MOVVC R1, sp MOVVC R2, #12 SWIVC XOS_ConvertCardinal4 SWIVC XOS_Write0 ADD sp, sp, #12 ] ] [ "$unit" <> "" ADRVCL R0, statusmess_$unit BLVC QuickLookup SWIVC XOS_WriteN ] SWIVC XOS_NewLine TEQ PC, #0 ; get around kernel bug: Z must be clear on exit EXIT 02 ; Set configuration - uses another macro due to assembler's limit on macro size SetConfig $string, $unit, $cmosbyte, $cmosbit, $cmossize, $shift, $eor, $expbyte, $expbit, $intvar, $intmul, $intbyte, $lut, $num MEND MACRO $lab SetConfig $string, $unit, $cmosbyte, $cmosbit, $cmossize, $shift, $eor, $expbyte, $expbit, $intvar, $intmul, $intbyte, $lut, $num [ "$lut" = "" :LOR: ("$lut" <> "" :LAND: "$num" <> "") MOV R1, R0 MOV R0, #10 :OR: 1:SHL:31 ; base 10, terminate at control char or space SWI XOS_ReadUnsigned EXIT VS [ "$lut" <> "" :LAND: "$num" <> "" ADRL R0, $lut BL status_scaninttable ] | ADRL R4, $lut BL status_scanstringtable EXIT VS ] ; Restrict R2 to a valid value, calculate mantissa (R3) and exponent (R4) if applicable [ "$shift" <> "" MOV R2, R2, LSR #$cmosbit ] [ "$cmossize" <> "" CMP R2, #(1 :SHL: $cmossize) - 1 | CMP R2, #&FF ] [ "$expbyte" = "" [ "$cmossize" <> "" MOVHI R2, #(1 :SHL: $cmossize) - 1 | MOVHI R2, #&FF ] | MOVLS R3, R2 MOVLS R4, #0 BLS %FT07 MOV R1, #10 DivRem R3, R2, R1, R0 ; R3 = R2 DIV 10, R2 = R2 MOD 10 CMP R3, #((1 :SHL: $cmossize) - 1) / 10 ; do we need to round down to 15? MOVEQ R3, #(1 :SHL: $cmossize) - 1 MOVEQ R4, #0 MOVHI R4, #1 CMP R3, #(1 :SHL: $cmossize) - 1 MOVHI R3, #(1 :SHL: $cmossize) - 1 07 MOV R2, R3, LSL R4 TEQ R4, #0 ADDNE R2, R2, R2, LSL #2 ] [ "$intvar" <> "" [ "$shift" <> "" MOV R1, R2, LSL #$cmosbit | MOV R1, R2 ] [ "$intmul" <> "" MOV R1, R1, LSL#1 ADD R1, R1, R1, LSL#2 ] [ "$lut" <> "" :LAND: "$num" <> "" ADRL R0, $lut LDR R1, [R0, R1, LSL#2] ] STR$intbyte R1, $intvar ] [ "$intvar" = "preferredpool" ; special case TEQ R1, #0 LDR R0, baseofsprites STREQ R0, baseofhisprites STRNE R0, baseoflosprites LDR R0, baseofromsprites STREQ R0, baseoflosprites STRNE R0, baseofhisprites [ windowsprite [ ThreeDPatch MOV R0, #0 BL reset_all_tiling_sprites | MOV R0, #-1 STR R0, tiling_sprite ] ] BL freelist ; mark cached sprite list invalid ] [ "$expbyte" = "" [ "$eor" <> "" [ $eor <> 0 [ "$shift" <> "" EOR R2, R2, #$eor :SHR: $cmosbit | EOR R2, R2, #$eor ] ] ] [ "$cmosbit" <> "" :LAND: "$cmossize" <> "" MOV R3, R2 MOV R0, #ReadCMOS MOV R1, #$cmosbyte SWI XOS_Byte EXIT VS BIC R2, R2, #((1 :SHL: $cmossize) - 1) :SHL: $cmosbit ORR R2, R2, R3, LSL #$cmosbit | MOV R1, #$cmosbyte ] MOV R0, #WriteCMOS SWI XOS_Byte | [ "$eor" <> "" [ $eor <> 0 EOR R3, R3, #$eor ] ] [ "$cmosbyte" = "$expbyte" MOV R0, #ReadCMOS MOV R1, #$cmosbyte SWI XOS_Byte EXIT VS BIC R2, R2, #(((1 :SHL: $cmossize) - 1) :SHL: $cmosbit) + (1 :SHL: $expbit) ORR R2, R2, R3, LSL #$cmosbit ORR R2, R2, R4, LSL #$expbit MOV R0, #WriteCMOS SWI XOS_Byte | MOV R0, #ReadCMOS MOV R1, #$cmosbyte SWI XOS_Byte EXIT VS BIC R2, R2, #((1 :SHL: $cmossize) - 1) :SHL: $cmosbit ORR R2, R2, R3, LSL #$cmosbit MOV R0, #WriteCMOS SWI XOS_Byte EXIT VS MOV R0, #ReadCMOS MOV R1, #$expbyte SWI XOS_Byte EXIT VS BIC R2, R2, #1 :SHL: $expbit ORR R2, R2, R4, LSL #$expbit MOV R0, #WriteCMOS SWI XOS_Byte ] ] EXIT MEND status_scaninttable ; In: R0 -> increasing integer table (terminated by -1) ; R2 = number to match ; Out: R2 = index into table of best match Entry MOV R4, R2 MOV R1, #0 01 LDR R3, [R0, R1, LSL #2] CMP R4, R3 MOVHS R2, R1 ADD R1, R1, #1 CMP R3, #-1 BNE %BT01 EXIT status_scanstringtable ; In: R0 -> string to match case-insensitively (not null terminated) ; R4 -> array of null-terminated strings, starting at 2-word boundaries (terminates with a null string) ; Out: R2 = index into array of match, or V set if no match Entry MOV R3, sp SUB sp, sp, #12 ; must be at least 2 longer than longest string MOV R2, sp 03 LDRB R1, [R0], #1 CMP R1, #' ' MOVLS R1, #0 ; also terminate at spaces STRB R1, [R2], #1 TEQ R2, R3 BNE %BT03 MOV R0, #0 STRB R0, [R2, #-1] ; just in case MOV R5, #0 MOV R6, #-1 MOV R1, sp MOV R3, #Collate_IgnoreCase 04 ADD R2, R4, R5, LSL #3 LDRB R14, [R2] TEQ R14, #0 BEQ %FT05 ; this signifies the end of the table MOV R0, #1 ; * commands are all in English SWI XTerritory_Collate EXIT VS MOVEQ R6, R5 ADD R5, R5, #1 B %BT04 05 ADD sp, sp, #12 ; matches with above CMP R6, #-1 MOVNE R2, R6 EXIT NE MOV R0, #0 ; "Bad configure option" SETV EXIT ; Units tokens for *Status statusmess_osunits DCB "OSUnits",0 statusmess_ds DCB "DeciSec",0 statusmess_osupersec DCB "OSUperSec",0 statusmess_osupersec2 DCB "OSUperSec2",0 ALIGN status_offon DCB "Off",0,0,0,0,0,"On",0,0,0,0,0,0,0,0,0,0 status_ramrom DCB "RAM",0,0,0,0,0,"ROM",0,0,0,0,0,0,0,0,0 status_clickrelease DCB "Click",0,0,0, "Release",0,0,0,0,0 ALIGN ; Code for handling *Configure/*Status WimpFlagsC_Code ConfigOption flags,,WimpFlagsCMOS,,,,,,,sysflags,,B statusmess_flags DCB "WimpFlags ",0 configmess_flags DCB "WimpFlags <D>",lf,cr,0 ALIGN WimpFontC_Code ConfigOption wimpfont,,DesktopFeaturesCMOS,1,4 statusmess_wimpfont DCB "WimpFont ",0 configmess_wimpfont DCB "WimpFont <D>",lf,cr,0 ALIGN WimpDragDelayC_Code ConfigOption dragdelay,ds,WimpDragTimeCMOS,0,4,,default_drag_timelimit,WimpDragMoveLimitCMOS,0,drag_timelimit,x10 statusmess_dragdelay DCB "WimpDragDelay ",0 configmess_dragdelay DCB "WimpDragDelay <D>",lf,cr,0 ALIGN WimpDragMoveC_Code ConfigOption dragmove,osunits,WimpDragMoveLimitCMOS,2,5,noshift,default_drag_movelimit,,,drag_movelimit,,B statusmess_dragmove DCB "WimpDragMove ",0 configmess_dragmove DCB "WimpDragMove <D>",lf,cr,0 ALIGN WimpDoubleClickDelayC_Code ConfigOption doubleclickdelay,ds,WimpDoubleClickTimeCMOS,0,4,,default_doubleclick_timelimit,WimpDoubleClickMoveLimitCMOS,0,doubleclick_timelimit,x10 statusmess_doubleclickdelay DCB "WimpDoubleClickDelay ",0 configmess_doubleclickdelay DCB "WimpDoubleClickDelay <D>",lf,cr,0 ALIGN WimpDoubleClickMoveC_Code ConfigOption doubleclickmove,osunits,WimpDoubleClickMoveLimitCMOS,2,5,noshift,default_doubleclick_movelimit,,,doubleclick_movelimit,,B statusmess_doubleclickmove DCB "WimpDoubleClickMove ",0 configmess_doubleclickmove DCB "WimpDoubleClickMove <D>",lf,cr,0 ALIGN WimpAutoMenuDelayC_Code ConfigOption automenudelay,ds,WimpAutoSubMenuTimeCMOS,0,4,,default_automenudelay,WimpAutoSubMenuTimeCMOS,4,automenu_timelimit,x10 statusmess_automenudelay DCB "WimpAutoMenuDelay ",0 configmess_automenudelay DCB "WimpAutoMenuDelay <D>",lf,cr,0 ALIGN WimpMenuDragDelayC_Code ConfigOption menudragdelay,ds,WimpMenuDragDelayCMOS,0,4,,default_menudragdelay,WimpMenuDragDelayCMOS,4,menudragdelay,x10 statusmess_menudragdelay DCB "WimpMenuDragDelay ",0 configmess_menudragdelay DCB "WimpMenuDragDelay <D>",lf,cr,0 ALIGN WimpIconBarSpeedC_Code ConfigOption iconbarspeed,osupersec,WimpAutoSubMenuTimeCMOS,5,3,,default_iconbarspeed,,,iconbar_scroll_speed,,,iconbarlogtable,numeric statusmess_iconbarspeed DCB "WimpIconBarSpeed ",0 configmess_iconbarspeed DCB "WimpIconBarSpeed <D>",lf,cr,0 ALIGN WimpIconBarAccelerationC_Code ConfigOption iconbaraccel,osupersec2,WimpMenuDragDelayCMOS,5,3,,default_iconbaraccel,,,iconbar_scroll_accel,,,iconbarlogtable,numeric statusmess_iconbaraccel DCB "WimpIconBarAcceleration ",0 configmess_iconbaraccel DCB "WimpIconBarAcceleration <D>",lf,cr,0 ALIGN [ SpritePriority WimpSpritePrecedenceC_Code ConfigOption sprite,,DesktopFeaturesCMOS,5,1,,0,,,preferredpool,,,status_ramrom statusmess_sprite DCB "WimpSpritePrecedence ",0 configmess_sprite DCB "WimpSpritePrecedence RAM|ROM",lf,cr,0 ALIGN ] [ BounceClose WimpButtonTypeC_Code ConfigOption button,,DesktopFeaturesCMOS,6,1,,0,,,buttontype,,B,status_clickrelease statusmess_button DCB "WimpButtonType ",0 configmess_button DCB "WimpButtonType Click|Release",lf,cr,0 ALIGN ] [ IconiseButton WimpIconiseButtonC_Code ConfigOption iconisebut,,WimpDragMoveLimitCMOS,7,1,,0,,,iconisebutton,,B,status_offon statusmess_iconisebut DCB "WimpIconiseButton ",0 configmess_iconisebut DCB "WimpIconiseButton On|Off",lf,cr,0 ALIGN ] [ StickyEdges WimpStickyEdgesC_Code ConfigOption sticky,,DesktopFeaturesCMOS,6,1,,0,,,stickyedges,,B,status_offon statusmess_sticky DCB "WimpStickyEdges ",0 configmess_sticky DCB "WimpStickyEdges On|Off",lf,cr,0 ALIGN ] [ PoppingIconBar WimpAutoFrontIconBarC_Code ConfigOption autofront,,WimpDoubleClickMoveLimitCMOS,7,1,,1,,,popiconbar,,B,status_offon statusmess_autofront DCB "WimpAutoFrontIconBar ",0 configmess_autofront DCB "WimpAutoFrontIconBar On|Off",lf,cr,0 ALIGN WimpAutoFrontDelayC_Code ConfigOption autofrontdelay,ds,WimpDoubleClickTimeCMOS,4,4,,default_autofrontdelay,WimpDoubleClickMoveLimitCMOS,1,popiconbar_pause,x10 statusmess_autofrontdelay DCB "WimpAutoFrontDelay ",0 configmess_autofrontdelay DCB "WimpAutoFrontDelay <D>",lf,cr,0 ALIGN ] [ Autoscr WimpAutoScrollDelayC_Code ConfigOption scrolldelay,ds,WimpDragTimeCMOS,4,4,,default_autoscrolldelay,WimpDragMoveLimitCMOS,1,autoscr_default_pause,,B statusmess_scrolldelay DCB "WimpAutoScrollDelay ",0 configmess_scrolldelay DCB "WimpAutoScrollDelay <D>",lf,cr,0 ALIGN ] [ ClickSubmenus WimpClickSubmenuC_Code ConfigOption clicksubmenu,,Misc1CMOS,0,1,,0,,,clicksubmenuenable,,B,status_offon statusmess_clicksubmenu DCB "WimpClickSubmenu ",0 configmess_clicksubmenu DCB "WimpClickSubmenu On|Off",lf,cr,0 ALIGN ] | WimpDragDelayC_Code MOV R1,#WimpDragTimeCMOS B %FT01 WimpDragMoveC_Code MOV R1,#WimpDragMoveLimitCMOS B %FT01 WimpDoubleClickDelayC_Code MOV R1,#WimpDoubleClickTimeCMOS B %FT01 WimpDoubleClickMoveC_Code MOV R1,#WimpDoubleClickMoveLimitCMOS B %FT01 WimpAutoMenuDelayC_Code MOV R1,#WimpAutoSubMenuTimeCMOS B %FT01 WimpMenuDragDelayC_Code MOV R1,#WimpMenuDragDelayCMOS B %FT01 WimpFontC_Code MOV R1,#DesktopFeaturesCMOS B %FT01 WimpFlagsC_Code MOV R1,#WimpFlagsCMOS 01 Push "R1,R12,LR" LDR wsptr,[R12] ; R12 --> workspace ; CMP R0,#1 BEQ printstatus BLO printsyntax ; MOV R1,R0 ; R1 --> string MOV R0,#&C000000A ; base 10, check terminator, <= 255 SWI XOS_ReadUnsigned Pull "R1,R12,PC",VS 01 LDRB R14,[R1],#1 ; check that nothing else follows CMP R14,#32 BEQ %BT01 MOVHI R0,#3 ; "Too many parameters" SETV HI Pull "R1,R12,PC",VS ; LDR R1,[sp,#0*4] TEQ R1,#WimpFlagsCMOS STREQB R2,sysflags BEQ %FT02 ; TEQ R1,#WimpDragTimeCMOS ADREQL R14,drag_timelimit ADDEQ R3,R2,R2,ASL #2 MOVEQ R3,R3,ASL #1 STREQ R3,[r14] EOREQ R2,R2,#default_drag_timelimit BEQ %FT02 ; TEQ R1,#WimpDragMoveLimitCMOS ADREQL R14,drag_movelimit STREQB R2,[r14] EOREQ R2,R2,#default_drag_movelimit BEQ %FT02 ; TEQ R1,#WimpDoubleClickTimeCMOS ADREQL R14,doubleclick_timelimit ADDEQ R3,R2,R2,ASL #2 MOVEQ R3,R3,ASL #1 STREQ R3,[r14] EOREQ R2,R2,#default_doubleclick_timelimit BEQ %FT02 ; TEQ R1,#WimpDoubleClickMoveLimitCMOS ADREQL R14,doubleclick_movelimit STREQB R2,[r14] EOREQ R2,R2,#default_doubleclick_movelimit BEQ %FT02 ; TEQ R1,#WimpAutoSubMenuTimeCMOS ADREQL R14,automenu_timelimit ADDEQ R3,R2,R2,ASL #2 MOVEQ R3,R3,ASL #1 STREQ R3,[r14] BEQ %FT02 ; TEQ R1,#DesktopFeaturesCMOS BNE notdesktopcmos CMP R2,#15 MyXError WimpBadConfFont,HI BVS %FT02 Push "R2" MOV R0,#ReadCMOS SWI XOS_Byte ; read current feature byte AND R0,R2,#&E1 ; mask out font Pull "R2" ORR R2,R0,R2, LSL #1 B %FT02 notdesktopcmos TEQ R1,#WimpMenuDragDelayCMOS ADREQL R14,menudragdelay ADDEQ R3,R2,R2,ASL #2 MOVEQ R3,R3,ASL #1 STREQ R3,[r14] BEQ %FT02 ; MOV R0,R2 BL validatemode [ Medusa BLVC copy_mode_specifier ] STRVC R0,currentmode ; needs R12 set up! EORVC R2,R2,#12 ; 12 is the default 02 MOVVC R0,#WriteCMOS ; don't forget to write the CMOS RAM! SWIVC XOS_Byte ; Pull "R1,R12,PC" LTORG fontoutofrange MakeErrorBlock WimpBadConfFont printstatus TEQ R1,#WimpFlagsCMOS ADREQL R0,statusmess_flags ; "WimpFlags " BEQ %FT01 TEQNE R1,#WimpDragMoveLimitCMOS ADREQL R0,statusmess_dragmove ; "WimpDragMove " BEQ %FT01 TEQNE R1,#WimpDragTimeCMOS ADREQL R0,statusmess_dragdelay ; "WimpDragDelay " BEQ %FT01 TEQNE R1,#WimpDoubleClickTimeCMOS ADREQL R0,statusmess_doubleclickdelay ; "WimpDoubleClickDelay " BEQ %FT01 TEQNE R1,#WimpDoubleClickMoveLimitCMOS ADREQL R0,statusmess_doubleclickmove ; "WimpDoubleClickMove " BEQ %FT01 TEQNE R1,#WimpAutoSubMenuTimeCMOS ADREQL R0,statusmess_automenudelay ; "WimpAutoMenuDelay " BEQ %FT01 TEQNE R1,#WimpMenuDragDelayCMOS ADREQL R0,statusmess_menudragdelay ; "WimpAutoDragDelay " BEQ %FT01 TEQNE R1,#DesktopFeaturesCMOS ADREQ R0,statusmess_wimpfont 01 ADRNE R0,statusmess_mode ; "WimpMode " SWI XOS_Write0 MOVVC R0,#ReadCMOS LDRVC R1,[sp,#0*4] SWIVC XOS_Byte ; R2 = configured Wimp mode Pull "R1,R12,PC",VS TEQ R1,#WimpFlagsCMOS TEQNE R1,#WimpAutoSubMenuTimeCMOS TEQNE R1,#WimpMenuDragDelayCMOS MOVEQ R0,R2 ; default flags and automenu = 0 BEQ %FT01 TEQNE R1,#WimpDragTimeCMOS EOREQ R0,R2,#default_drag_timelimit BEQ %FT01 TEQNE R1,#WimpDragMoveLimitCMOS EOREQ R0,R2,#default_drag_movelimit BEQ %FT01 TEQNE R1,#WimpDoubleClickTimeCMOS EOREQ R0,R2,#default_doubleclick_timelimit BEQ %FT01 TEQNE R1,#WimpDoubleClickMoveLimitCMOS EOREQ R0,R2,#default_doubleclick_movelimit BEQ %FT01 TEQNE R1,#DesktopFeaturesCMOS ANDEQ R0,R2,#&1E MOVEQ R0,R0,LSR #1 01 EORNE R0,R2,#12 ; default mode = 12 SUB sp,sp,#4 MOV R1,sp MOV R2,#4 SWIVC XOS_ConvertCardinal1 ; print mode number SWIVC XOS_Write0 ADD sp,sp,#4 ; Pull "R1,R12,PC",VS LDR R1,[sp,#0*4] TEQ R1,#WimpFlagsCMOS TEQNE R1,#WimpModeCMOS TEQNE R1,#DesktopFeaturesCMOS SWIEQ XOS_NewLine ; followed by NewLine Pull "R1,R12,PC",EQ ; TEQ R1,#WimpDragMoveLimitCMOS TEQNE R1,#WimpDoubleClickMoveLimitCMOS ADREQ R0,statusmess_osunits ; " OS Units" ADRNE R0,statusmess_cs ; " * 1/10 second" BL QuickLookup SWIVC XOS_WriteN SWIVC XOS_NewLine ; followed by NewLine ; Pull "R1,R12,PC" statusmess_wimpfont DCB "WimpFont ",0 statusmess_flags DCB "WimpFlags ",0 statusmess_mode DCB "WimpMode ",0 statusmess_dragmove DCB "WimpDragMove ",0 statusmess_dragdelay DCB "WimpDragDelay ",0 statusmess_doubleclickdelay DCB "WimpDoubleClickDelay ",0 statusmess_doubleclickmove DCB "WimpDoubleClickMove ",0 statusmess_automenudelay DCB "WimpAutoMenuDelay ",0 statusmess_menudragdelay DCB "WimpMenuDragDelay ",0 statusmess_osunits DCB "OSUnits",0 statusmess_cs DCB "CentSec",0 configmess_wimpfont DCB "WimpFont <D>",lf,cr,0 configmess_flags DCB "WimpFlags <D>",lf,cr,0 configmess_mode DCB "WimpMode <D>",lf,cr,0 configmess_dragmove DCB "WimpDragMove <D>",lf,cr,0 configmess_dragdelay DCB "WimpDragDelay <D>",lf,cr,0 configmess_doubleclickdelay DCB "WimpDoubleClickDelay <D>",lf,cr,0 configmess_doubleclickmove DCB "WimpDoubleClickMove <D>",lf,cr,0 configmess_automenudelay DCB "WimpAutoMenuDelay <D>",lf,cr,0 configmess_menudragdelay DCB "WimpMenuDragDelay <D>",lf,cr,0 ALIGN printsyntax TEQ R1,#WimpFlagsCMOS ADREQ R0,configmess_flags BEQ %FT01 TEQNE R1,#WimpDragMoveLimitCMOS ADREQ R0,configmess_dragmove BEQ %FT01 TEQNE R1,#WimpDragTimeCMOS ADREQ R0,configmess_dragdelay BEQ %FT01 TEQNE R1,#WimpDoubleClickTimeCMOS ADREQ R0,configmess_doubleclickdelay BEQ %FT01 TEQNE R1,#WimpDoubleClickMoveLimitCMOS ADREQ R0,configmess_doubleclickmove BEQ %FT01 TEQNE R1,#WimpAutoSubMenuTimeCMOS ADREQ R0,configmess_automenudelay BEQ %FT01 TEQNE R1,#WimpMenuDragDelayCMOS ADREQ R0,configmess_menudragdelay BEQ %FT01 TEQNE R1,#DesktopFeaturesCMOS ADREQL R0,configmess_wimpfont 01 ADRNEL R0,configmess_mode SWI XOS_Write0 Pull "R1,R12,PC" ] ; ; Entry: R0 = desired mode number ; Exit: mode change effected, pointer re-established etc. ; palette is also recalculated, and screen cleared to colour 15 ; broadcast will be sent to all tasks, notifying them of the change ; if the screen size changes, a flag is set so they'll be re-opened ; SWIWimp_SetMode MyEntry "SetMode" BL validatemode BVS ExitWimp LDR R2,taskcount CMP R2,#0 BNE %FT01 [ Medusa BL copy_mode_specifier ] STR R0,currentmode ; just alter value for next time 01 LDR R1,commandflag ; you can change mode without penalty ORR R14,R1,#cf_suspended ; since the desktop is intact STR R14,commandflag CMP R2,#0 BLNE int_setmode STR R1,commandflag TST R1,#cf_active ; if command window already active, SWINE XOS_WriteI+4 ; try not to confuse the user! B ExitWimp validatemode Push "R0-R3,LR" ; MOV R1,#VduExt_ModeFlags SWI XOS_ReadModeVariable MOVCSS r0,#1 ; For the NE on MyXError below ! Carry preserved BCS %FT01 ; TST R2,#Flag_NonGraphic ; NE => this is a non-graphic mode BNE %FT01 ; MOV R1,#VduExt_Log2BPP SWI XOS_ReadModeVariable MOV R3,R2 MOV R1,#VduExt_Log2BPC SWI XOS_ReadModeVariable TEQ R2,R3 ; NE => this is a double-pixel mode 01 MyXError WimpBadMode,NE ; STRVS R0,[sp] Pull "R0-R3,PC" MakeErrorBlock WimpBadMode ; Set up default (configured) amount of screen memory defaultscreensize Push "R1-R2,LR" ; ADR R0,vduin_scrsize ; read current screen size ADR R1,tempworkspace SWI XOS_ReadVduVariables ; MOVVC R0,#0 SWIVC XOS_ReadSysInfo ; R0 = default screen size LDRVC R1,tempworkspace ; R1 = current screen size SUBVC R1,R0,R1 ; R1 = amount to add to screen ; Debug dy,"Set default screen size: R1=",R1 ; MOVVC R0,#2 ; screen SWIVC XOS_ChangeDynamicArea ; CLRV Pull "R1-R2,PC" ; ignore 'Unable to move memory' vduin_scrsize DCD VduExt_TotalScreenSize DCD -1 [ Medusa ; copy_mode_specifier ; entry R0 points to mode specifier block (-1 terminated), contents copied to ; RMA and routine exits with R0 pointing to copy OR V set and R0-> original. copy_mode_specifier CMP R0,#256 MOVLO PC,LR ; V will be clear Push "R0-R3,LR" MOV R2,#20 ; skip permanent bit ADD R0,R0,R2 5 LDR R14,[R0],#4 ADD R2,R2,#4 CMP R14,#-1 BNE %BT5 ; need R2 of RMA MOV R3,R2 MOV R0,#ModHandReason_Claim BL XROS_Module LDRVS R0,currentmode STRVS R0,[SP] ; use old mode if can't claim Pull "R0-R3,PC",VS MOV R3,R2 LDR R1,[SP] 7 LDR R14,[R1],#4 STR R14,[R3],#4 CMP R14,#-1 BNE %BT7 SUB R14,R3,R2 ; -1 is allowed in first bit CMP R14,#24 BLO %BT7 ; R2 -> copy of specifier STR R2,[SP] CLRV Pull "R0-R3,PC" ] ;.......................................................................... ; Change the current Wimp mode, preserving the pointer position ; [modechanged] set only if the current task is a new-style one ; The flag is reset if an old-style task subsequently starts up ; If the flag is set when Wimp_Poll is called, a set of messages is sent ; ; NB: In Wimp 2.36 and later, the Mode_Change message is only issued if the ; mode has actually changed (ie. is not the same as before!) ; The VDU 22,<mode> must still be issued, to set the (non-wimp) mode int_setmode ROUT Push "R0-R2,LR" [ ChildWindows BL int_flush_opens ; do this BEFORE the mode change ] MOV R14,#6 ; read current pointer position STRB R14,[sp,#-8]! ; (not buffered) MOV R1,sp ; NB: don't use code 4 (mouse posn) MOV R0,#&15 ; cos there's a bug in Risc OS !!! SWI XOS_Word LDR R0,[sp,#8] ; skip OS_Word block to get mode number [ Medusa CMP R0,#256 BLO %FT20 ; been given a mode specifier, must copy this before calling screen SWI. LDR R14,currentmode CMP R0,R14 BLNE copy_mode_specifier ; don't copy if new mode same as old one LDRVS R0,currentmode ; sadly can't change if we haven't got room to copy ; R0 has mode specifier Push "R0-R1" MOV R1,R0 MOV R0,#0 ; set screen mode CLRV SWI XOS_ScreenMode Push "R0,R2" [ true ADRVSL R14,greys_mode LDRVSB R0,[R14,#1] ; last mode STRVSB R0,[R14] ] MOVVS R2,R1 ; if fails, then free copy LDRVS R1,currentmode LDRVC R2,currentmode BLVS recalcmodevars ; if it fails, then this wont happen CMP R2,#256 BLO %FT12 CMP R2,R1 ; old mode=new mode BEQ %FT12 MOV R0,#ModHandReason_Free BL XROS_Module 12 Pull "R0,R2" STR R1,currentmode 15 Pull "R0-R1" B %FT40 20 LDR R14,currentmode CMP R14,#256 BLO %FT30 ; need to free current mode's specifier block if change succeeds CLRV Push "R14" SWI XOS_WriteI+22 SWIVC XOS_WriteC Pull "R14" STRVC R0,currentmode BVS %FT40 ; old mode still valid Push "R0-R2" MOV R0,#ModHandReason_Free MOV R2,R14 BL XROS_Module Pull "R0-R2" B %FT40 ; if V set then something wrong, still try and sort out screen mode though 30 ] CLRV ; CMP SWI XOS_WriteI+22 SWIVC XOS_WriteC STRVC R0,currentmode ; remember for later ; CLRV ; still execute the rest if it fails! 40 MOV R14,#3 ; set mouse position STRB R14,[R1] ; (not quite logical, Captain) MOV R0,#&15 SWI XOS_Word ; restore mouse position ADD sp,sp,#12 ; correct stack (discard R0) ; MOV R0,#2 ; shrink screen memory as small as poss MOV R1,#1:SHL:31 SWI XOS_ChangeDynamicArea CLRV ; ignore 'Unable to move memory' ; set flag to indicate mode changed (if new mode is indeed different!) LDR R0,scrx1 LDR R1,lastmode_x1 CMP R0,R1 LDRHS R0,scry1 LDRHS R1,lastmode_y1 CMPHS R0,R1 MOVHS R14,#0 MOVLO R14,#ws_onscreenonce ; force onto screen if getting smaller STR R14,forceflags ; LDR R14,singletaskhandle CMP R14,#0 ASSERT task_unused = &80000000 LDRGT R14,[wsptr,R14] ; only counts if task is active CMPGT R14,#0 MOVLE R14,#1 STRLEB R14,modechanged ; don't do it if single-tasking ; set up screen variables and graphics state nomodemess BL recalcpalette ; do this first in case ptr has palette BLVC int_allbutmode ; sets up mode variables etc. [ Medusa ADRL R14,greys_mode LDRB R14,[R14] TEQ R14,#0 BLNE recalc_greys_palette ] ; attempt to recache the borders if required LDRB R0,modechanged ; has the mode been changed? TEQ R0,#0 BLNE maketoollist ; re-calcuate border based information [ outlinefont BLNE FindFont ; attempt to re-cache the system font ] ; LDRVC handle,backwindowhandle Abs handle,handle,VC LDRVCB R0,[handle,#w_wbcol] ; assume wf_realcolours not set BLVC background BVS %FT90 [ windowsprite :LAND: false LDRB R0,[handle,#w_wbcol] CMP R0,#1 SWINE XOS_WriteI+16 ; CLG BLEQ plotspritebackground | SWI XOS_WriteI+16 ] 90 Pull "R1-R2,PC" LTORG ;.......................................................................... ; Entry: userblk --> user block (R1 on entry to Wimp) ; R2 =&45555254 ("TRUE") then read as 24 bit values, not 12 bit ; Exit: 20 palette entries set up from block ; palette is then recomputed SWIWimp_SetPalette ROUT MyEntry "SetPalette" CMP userblk,userblk,ASR #31 ADREQL userblk,emergencypalette ; set default if R1 <= 0 BL int_setpalette B ExitWimp ;.............................................................................. int_setpalette Push "R1-R4,LR" ; [ false MOV R0,#0 ADRL R3,greys_mode STRB R0,[R3] ; as we're setting the palette, this can no ] ; longer be a grey mode. LDR R1,=&45555254 ; is this a special setting of 24bit values? TEQ R1,R2 MOVEQ R2,#0 MOVNE R2,#4 ; R2 = shift right for all entries LDR R3,=&F0F0F000 ; R3 = mask to apply to all entries ORREQ R3,R3,R3,LSR #4 ; if R2 ="TRUE" on entry read as 24bit values ; ; BL getpalpointer ; address the palette table ADRL R14,paltable ; BJGA 16-Jun-00: don't overwrite the values set by Wimp_SetColourMapping MOV R1,#16 ; copy the first 16 entries 00 LDR R4,[userblk],#4 AND R4,R4,R3 ; extract only the useful bits ORR R4,R4,R4,LSR R2 ; and then munge as required STR R4,[R14],#4 ; store into correct palette table SUBS R1,R1,#1 BNE %BT00 ; looping until all entries copied ; ADRL R14,othercolours ; -> table of other colours to copy MOV R1,#4 00 LDR R4,[userblk],#4 AND R4,R4,R3 ; extract only the useful bits ORR R4,R4,R4,LSR R2 ; and then munge as required STR R4,[R14],#4 ; store into correct palette table SUBS R1,R1,#1 BNE %BT00 ; looping until all entries copied ; BL recalcpalette ; recache palette information CLRV Pull "R1-R4,PC" ;.......................................................................... ; In userblk --> user block (R1 on entry to Wimp) ; R2 = &45555254 ("TRUE") then read back 24 bit values, rather than 12 bit. ; Out 20 palette entries copied to block SWIWimp_ReadPalette ROUT MyEntry "ReadPalette" BL getpalpointer ; R14 -> palette table to copy to caller ; LDR R3,=&45555254 TEQ R2,R3 ; did the caller specify the magic word? LDR R2,=&F0F0F000 ; setup a suitable mask for returning 12 bit values ORREQ R2,R2,R2,LSR #4 ; if R2 contains magic word then return full 24 bit values ; LDR R1,log2bpp CMP R1,#3 BHI get_16bpp_GCOLS MOV R1,#16 ; copy the first 16 entries from the table 01 LDR R3,[R14],#4 AND R3,R3,R2 ; apply the mask to this value ; Push "R0,R14" ; [ false LDR R0,log2bpp CMP R0,#3 ; is the depth of this mode valid [ false RSBHI R0,R1,#16 ; R0 is wimp colour ORRHI R3,R3,R0 ] BHI %FT02 ] ; if not then ignore it ; MOV R0,R3 SWI XColourTrans_ReturnGCOL ; process into a colour byte ORR R3,R3,R0 ; and then combine with palette entry 02 Pull "R0,R14" ; restore sensitive registers ; STR R3,[userblk],#4 ; and then store in the specified buffer SUBS R1,R1,#1 BNE %BT01 ; looping until they have all been copied done_palette ADRL R1,othercolours LDMIA R1,{R3-R6} ; extract the border and three mouse colours AND R3,R3,R2 AND R4,R4,R2 AND R5,R5,R2 AND R6,R6,R2 ; extract only the required bits STMIA userblk!,{R3-R6} ; and store into the block ; B ExitWimp LTORG ; get_16bpp_GCOLS ; R14 is palette pointer ; userblk is destination ; R2 is mask (F0F0F000 etc.) Push "R0,R14" MOV R0,#12 ; mode 12 is 16 colour ADRL R1,emergencypalette MOV R3,R14 SUB SP,SP,#16 MOV R4,SP ; will always be 16 bytes Push R2 MOV R2,#-1 MOV R5,#0 SWI XColourTrans_SelectTable Pull R2 ADDVS SP,SP,#24 BVS ExitWimp MOV R1,#16 01 LDR R0,[R3],#4 AND R0,R0,R2 LDRB R14,[R4],#1 ORR R0,R0,R14 STR R0,[userblk],#4 SUBS R1,R1,#1 BNE %BT01 ADD SP,SP,#16 Pull "R0,R14" B done_palette ;.......................................................................... ; Called from int_setmode and Wimp_Initialise (if old-style task) ; Does not set mode or palette, but does set up mode variables ; From Wimp 2.20 onwards, it also doesn't reopen all the windows! ; Called from Wimp_Initialise for old-style tasks, int_setmode otherwise ; [modechanged] = 1 => re-open backdrop and iconbar int_allbutmode ROUT Push "LR" ; BL readvduvars2 ; including screen size BL calcborders ; ignore errors ; ; assert that there are no opens pending at this point ; [ debug :LAND: ChildWindows LDRB R14,openspending TEQ R14,#0 MOVNE R14,#0 STRNE R14,[R14] ; crash! ] ; ; recalculate border positions for all (created) windows ; Push "R1-R2,x0,y0,x1,y1,handle" ; ADRL R2,allwinds+lh_forwards-ll_forwards 01 LDR R2,[R2,#ll_forwards] LDR R14,[R2,#ll_forwards] CMP R14,#nullptr BEQ %FT02 SUB handle,R2,#w_all_link ASSERT R10>y1 Push "R10,R11" ADD R14,handle,#w_wax0 LDMIA R14,{x0,y0,x1,y1,R10,R11} LDR R0,dx_1 BIC x0,x0,R0 BIC x1,x1,R0 BIC R10,R10,R0 ; scroll x LDR R0,dy_1 BIC y0,y0,R0 BIC y1,y1,R0 BIC R11,R11,R0 ; scroll y STMIA R14,{x0,y0,x1,y1,R10,R11} [ ChildWindows ADD R14,R14,#w_old_wax0 - w_wax0 ; keep 'old' position in step STMIA R14,{x0,y0,x1,y1,R10,R11} ] Pull "R10,R11" BL calc_w_x0y0x1y1 ADD R14,handle,#w_x0 STMIA R14,{x0,y0,x1,y1} [ ChildWindows ADD R14,handle,#w_old_x0 ; keep 'old' outline in step STMIA R14,{x0,y0,x1,y1} ] B %BT01 02 Pull "R1,R2,x0,y0,x1,y1,handle" ; ; return appropriate OpenWindowRequest for all open windows (except panes) ; ; Wimp 2.13 onwards actually do this when Wimp_Poll has finished delivering ; all messages. This allows for the window setup to change in response to ; the Message_ModeChange. ; ; Wimp 2.14 onwards issues the Open_Window_Requests for the rearmost windows ; first, to cope with the problems of backdrop windows. ; ; do the background window and the iconbar first, to avoid problems with ; user 'backdrop' windows LDRB R14,modechanged ; only re-open backdrop TEQ R14,#0 ; if a Message_ModeChange will follow BEQ skip_backdrop LDR R0,backwindowhandle ; open back window at full size MOV R1,R0 ; open at same level (the very back) BL openfullsize ; keep at full extent skip_backdrop ; restore soft characters etc. ; ADR R0,initvdustring1 MOV R1,#endvdustring1-initvdustring1 SWI XOS_WriteN ; [ UTF8 BL read_current_alphabet BEQ %FT88 ADR R0, initvdustring1a MOV R1, #endvdustring1a-initvdustring1a SWI XOS_WriteN ] ; LDR R0,tool_area TEQ R0,#0 ; have any tools been installed? ADREQ R0,initvdustring2 MOVEQ R1,#endvdustring2-initvdustring2 SWIEQ XOS_WriteN ; No, so redefine glyphs 88 LDR R1,scrx0 LDR R2,scry1 SUB R2,R2,#1 ; move to top-left of window MOV R0,#4 SWI XOS_Plot ; (so VDU 5 text is visible) ; ; set up character size/spacing to always be 16x32 OS units ; BL set16x32chars ; ; mark screen invalid (as we just cleared it!) ; MOV R0,#invalidrects BL loserects ; screen may shrink! ; MOV cx0,#-bignum MOV cy0,#-bignum MOV cx1,#bignum MOV cy1,#bignum BL markinvalid_cx0cy0cx1cy1 ; LDR R14,dragtype ; pointer is off during 2-D scroll TEQ R14,#drag_scrollboth BLNE pointeron ; MOV R0,#21 ; flush mouseahead buffer! MOV R1,#9 SWI XOS_Byte ; ; re-open icon bar at correct size ; this and the backdrop window are done before Mode_Change is issued ; all other windows are done on the next Wimp_Poll ; Wimp 2.20 onwards only do this in int_setmode ; LDRB R14,modechanged ; don't re-open icon bar TEQ R14,#0 ; unless Message_ModeChange will follow Pull "PC",EQ LDR handle,iconbarhandle CMP handle,#nullptr BEQ %FT01 MOV R2,handle ; R2 = bhandle (ie. open at same height) BL openiconbar ; open at correct size ADRVC R7,iconbarleft BLVC recalcposns ADRVC R7,iconbarright BLVC recalcposns 01 Pull "PC" ; characters always defined by the Wimp initvdustring1 DCB 5 DCB 23,17,4,1,0,0,0,0,0,0 ; use native ARM ecfs DCB 23,16,&40,&BF,0,0,0,0,0,0 ; no vdu 5 wraparound DCB 26 ; for reading graphics window size [ UTF8 endvdustring1 ALIGN ; characters only defined if alphabet <> UTF-8 initvdustring1a ] [ :LNOT: Euro DCB 23,&80,&03,&03,&06,&06,&76,&1C,&0C,&00 ] DCB 23,&83,&FE,&92,&92,&F2,&82,&82,&FE,&00 DCB 23,&84,&66,&99,&81,&42,&81,&99,&66,&00 DCB 23,&88,&18,&28,&4F,&81,&4F,&28,&18,&00 DCB 23,&89,&18,&14,&F2,&81,&F2,&14,&18,&00 DCB 23,&8A,&3C,&24,&24,&E7,&42,&24,&18,&00 DCB 23,&8B,&18,&24,&42,&E7,&24,&24,&3C,&00 [ UTF8 endvdustring1a | endvdustring1 ] ALIGN ; characters only defined if not tools present initvdustring2 DCB 23,&81,&F0,&90,&F0,&1F,&1F,&1F,&1F,&00 DCB 23,&82,&E0,&E0,&E0,&1F,&11,&11,&1F,&00 DCB 23,&85,&FC,&FC,&FF,&E1,&E1,&21,&3F,&00 endvdustring2 ALIGN set16x32chars Push "R1-R2,LR" MOV R1,#16 LDR R14,log2px MOV R1,R1,ASR R14 ; bits 0..15 of R1 := x-mag MOV R2,#32:SHL:16 LDR R14,log2py ORR R1,R1,R2,ASR R14 ; bits 16..31 of R1 := y-mag LDR R0,hdrword MOV R2,#0 Push "R0-R2" MOV R0,sp MOV R1,#10 SWI XOS_WriteN ADD sp,sp,#12 Pull "R1-R2,PC" hdrword DCB 23,17,7,6 ; header for VDU 5 char size spec. taskidentifier DCB "TASK" ; used to identify when R0 = taskhandle ; ; Entry: if R1 = "TASK", then ; R0 = task handle of task to be deleted ; otherwise close down current task ; SWIWimp_CloseDown MyEntry "CloseDown" ; MOV R2,#svc_closedown BL closedown ; B ExitWimp ; ; Entry: R2 = svc_initialise ==> this is because someone else is initialising ; R2 = svc_closedown ==> this is because Wimp_CloseDown was called ; ie: you must not object to it ; closedown Push "LR" ; MOV R4,R2 ; keep this (svc_initialise/closedown) ; LDR R5,taskidentifier TEQ R1,R5 ; R1="TASK" ==> use R0 as task handle BEQ %FT01 ; note, R1 = 0 if called due to initialisation ; LDR R5,taskhandle ; close down current task LDR R6,[wsptr,R5] TST R6,#task_unused ; (if alive) Pull "PC",NE LDR R14,[R6,#task_flagword] ; get full task handle MOV R14,R14,LSR #flag_versionbit ORR R2,R5,R14,LSL #flag_versionbit B %FT02 01 MOV R2,#0 ; ensure <> "TASK" STR R2,[sp,# 0*4 + 4] ; store in stack, to be returned in R1 MOV R2,R0 ; R2 = external task handle (see below) BL validtask_alive ; R5 = internal task handle if OK BVC %FT02 ; R6 --> block (if alive) CLRV Pull "PC" ; assume task deleted if invalid 02 ; ; R2 = external task handle ; R4 = 0 / 1 (for service call) ; R5 = internal task handle ; R6 --> task block ; ; issue service call to see if anyone objects to this closedown ; R0 = 0 ==> this is a straight closedown (you must not object) ; R0 > 0 ==> someone else is trying to muscle in (you can object to it) ; R1 = Service_WimpCloseDown ; R2 = task handle of task being blown away ; MOV R0,R4 ; R0 = 0/1 MOV R1,#Service_WimpCloseDown SWI XOS_ServiceCall ; R2 = external task handle CMP R0,#2 ; R0<2 ==> no error, else R0-->error SETV CS Pull "PC",VS ; task is allowed to object if R0=1 ; LDR R1,pendingtask ; suspend pending task LDR R14,taskhandle Push "R1,R14" ; restore later STR R6,pendingtask ; mark task block for deletion! ; (R6 returned from validtask_alive) MOV R4,R6 ; R4 not needed any more BL killfpblock ; kills [R4,#task_fpblock] ; STR R5,taskhandle BL removeallmessages ; remove all the messages ; [ Swapping LDR R14,[R6,#task_file] TEQ R14,#0 BLNE close_swap ; Close swap file for this task ] ; BL wipewindows ; delete anything owned by this task ; ; send Message_TaskCloseDown broadcast ; MOV R14,#ms_data STR R14,[sp,-R14]! LDR R14,=Message_TaskCloseDown STR R14,[sp,#ms_action] MOV R14,#0 STR R14,[sp,#ms_yourref] MOV R0,#User_Message MOV R1,sp MOV R2,#0 BL int_sendmessage ADD sp,sp,#ms_data ; MOV R0,#task_unused ; delete the task STR R0,[wsptr,R5] Push "handle" MOV handle,R5 BL DeletePollTask ; Remove from poll list Pull "handle" LDR R14,taskcount SUBS R14,R14,#1 STRGE R14,taskcount Debug task1,"Deleting task - handle, left: ",#taskhandle,R14 BGT ExitClose ; ; when the last task is deleted, reset *FX settings ; and reset the original quit handler ; closelast BL deletemessagequeue ; these can't be delivered! BL restorepages ; put everything back to normal! Debug task1,"Restoring initial quit handler" ; MOV R0,#UpCallV ; get off the vector! ADRL R1,UpCallCode BL release ; [ mousecache MOV R0,#TickerV ; tidy the mouse handler ADRL R1,MouseCallEveryHandler BL release ] [ NewErrorSystem [ WatchdogTimer ADRL R0,BreakWatchdogHandler MOV R1,WsPtr SWI XOS_RemoveTickerEvent | MOV R0,#EventV ADRL R1,BreakWatchdogHandler MOV R2,WsPtr SWI XOS_Release MOV R0,#13 MOV R1,#Event_Keyboard SWI XOS_Byte ] ] ; [ outlinefont BL LoseFont ; release the font (if claimed!) ] ; ADR R14,wimpquithandler LDMIA R14,{R1-R3} MOV R0,#ExitHandler SWI XOS_ChangeEnvironment BVS ExitClose ; BL restorekeycodes ; LDR R0,singletaskhandle LDR R1,taskhandle TEQ R0,R1 BEQ ExitClose ; old wimp didn't do this! ; MOV R0,#1 ; Read configured mode SWI XOS_ReadSysInfo MOVVS R0,#27 [ Medusa MOV R1,R0 MOV R0,#0 SWI XOS_ScreenMode | SWI XOS_WriteI+22 ; change to configured mode SWI XOS_WriteC ] ; BL defaultscreensize BL LoseMessages ; [ Stork LDR R0,WimpPortableFlags ; is the Portable installed? | LDR R0,WimpPortableFlag ; is the Portable installed? ] TEQ R0,#0 BEQ ExitClose ; no, so don't tidy up non-existant ticker routines ; Push "R0-R1" ; [ Stork TST R0, #PortableFeature_Speed MOVNE R0,#0 MOVNE R1,#0 SWINE XPortable_Speed ; make it go fast! | MOV R0,#0 MOV R1,#0 SWI XPortable_Speed ; make it go fast! ] ; ADRL R0,CallEveryHandler MOV R1,WsPtr SWI XOS_RemoveTickerEvent ; remove the ticker handler ; Pull "R0-R1" ExitClose LDR R14,taskhandle Pull "R2,R5" ; R5 = original task handle TEQ R5,R14 ; if the current task was closed down, BEQ postclosedown ; don't reclaim memory just yet BL deallocatependingtask ; otherwise kill it straight away! STR R2,pendingtask ; restore correct pending/current task STR R5,taskhandle Pull "PC" ; return to caller LTORG postclosedown LDR R14,singletaskhandle ; single tasks are treated suspiciously TEQ R5,R14 ; anyway LDRNE R14,taskcount ; no need for command window TEQNE R14,#0 ; when last task exits either! Pull "PC",EQ ; LDR R14,commandflag ; if no command window, TEQ R14,#cf_dormant ; set one pending to cover our backside ADREQ R0,nullstring BLEQ int_commandwindow ; (don't trust parent!) ; Pull "PC" nullstring DCB 0 ALIGN restorekeycodes EntryS "R0-R3" ; ADR R3,oldfxstatus MOV R0,#4 LDRB R1,[R3],#1 ; *FX 4,<n> SWI XOS_Byte ; MOV R0,#219 LDRB R1,[R3],#1 ; *FX 219,<x> (TAB key) MOV R2,#0 SWI XOS_Byte ; MOV R0,#221 01 LDRB R1,[R3],#1 MOV R2,#0 Push "R0" SWI XOS_Byte ; *FX 221,<n> to *FX 228,<n> Pull "R0" ADD R0,R0,#1 CMP R0,#228 BLS %BT01 ; MOV R0,#9 ; *FX 9,<n> LDRB R1,[R3],#1 SWI XOS_Byte MOV R0,#10 ; *FX 10,<n> LDRB R1,[R3],#1 SWI XOS_Byte ; LDR R14,singletaskhandle ; old Wimp didn't touch this! CMP R14,#nullptr MOVEQ R0,#229 LDREQB R1,[R3],#1 MOVEQ R2,#0 SWIEQ XOS_Byte ; *FX 229,<x> ; EXITS ; forget errors ; In [pendingtask] -> task block to be deallocated ; Out block deallocated, along with slot block and fp register block deallocatependingtask Push "R2,R4,LR" ; LDR R4,pendingtask ; delete task block (gone for good) CMP R4,#0 BMI %FT01 LDR R2,[R4,#task_slotptr] BL deallocate ; reclaim the memory BL killfpblock ; R4 -> task block here MOV R0,#ModHandReason_Free MOV R2,R4 BL XROS_Module MOV R14,#nullptr ; since the task is dead anyway STR R14,pendingtask 01 Pull "R2,R4,PC" ; In R4 -> task block ; Out [R4,#task_fpblock] = 0, block deallocated (if was present) killfpblock EntryS "R0,R2" LDR R2,[R4,#task_fpblock] Debug fp,"killfpblock: task, fp block =",R4,R2 TEQ R2,#0 MOVNE R0,#ModHandReason_Free BLNE XROS_Module MOV R14,#0 STR R14,[R4,#task_fpblock] EXITS ; ignore errors [ Swapping ;;----------------------------------------------------------------------------------- ;;close_swap - Close swap file for a task , task must have one. ;;Entry: ;; R6 -> Task block. ;; close_swap Push "R0-R5,LR" Debug swp,"Closing swap file for task" MOV R0,#0 ; Close file LDR R1,[R6,#task_file] TEQ R1,#0 BEQ %FT02 ; If no file, don't close. SWI XOS_Find ANDVSS R0,R0,#0 ; Ignore errors ADRL R1,swap_path ADRL R3,swapping LDR R3,[R3] ADD R1,R1,R3 ADD R0,R6,#task_filename 01 ; Copy filename. LDRB R14,[R0],#1 STRB R14,[R1],#1 TEQ R14,#0 BNE %BT01 MOV R0,#OSFile_Delete ADRL R1,swap_path SWI XOS_File ANDS R0,R0,#0 ; Ignore errors Debug swp,"close: set file to ",R0 STR R0,[R6,#task_file] STR R0,[R6,#task_filename] 02 Pull "R0-R5,PC" ;;--------------------------------------------------------------------------- ;; Increment swap file name by 1. ;; increment_swap_filename Push "R0-R1,LR" ADRL R0,swap_filename SUB R1,R0,#1 ADD R0,R0,#2 01 LDRB R14,[R0] ADD R14,R14,#1 CMP R14,#"Z" MOVHI R14,#"A" STRB R14,[R0],#-1 CMPHI R0,R1 BHI %BT01 Pull "R0-R1,PC" ] ;----------------------------------------------------------------------------- ; Called when the module is initialised ;----------------------------------------------------------------------------- initptrs Push "R0-R11,LR" ; ; initialise task data (set pointers to &80000000) ; ADR R14,taskstack STR R14,taskSP ; ADRL R5,taskpointers ; R5 --> task data pointer array MOV R6,#maxtasks MOV R14,#task_unused ; all tasks unused inittasks STR R14,[R5],#4 SUBS R6,R6,#1 BNE inittasks ADR R14, PollTasks STR R14, PollTaskPtr ; No tasks in pollword list ; MOV R14,#0 ; no tasks alive STR R14,taskcount STRB R14,modechanged STRB R14,addtoolstolist ; flag as not adding tools into sprite list for sorting! ; ; clear all window ptrs (including the redraw handle) ; MOV R0,#nullptr2 ; NB wimp not in control yet STR R0,freepool ; MOV R0,#nullptr STR R0,singletaskhandle STR R0,backwindow STR R0,commandhandle STR R0,redrawhandle STR R0,caretdata [ CnP STR R0,ghostcaretdata STR R0,selectionwindow ] STR R0,menucaretwindow STR R0,pendingtask ; STR R0,border_iconselected STR R0,border_windowselected ; ; Initialise all winds list to be empty ; ADRL R1, allwinds+lh_indicator STR R1, allwinds+lh_forwards [ ChildWindows STR R0, allwinds+lh_indicator | MOV R1, #nullptr STR R1, allwinds+lh_indicator ] ADRL R1, allwinds+lh_forwards STR R1, allwinds+lh_backwards ; ; Initialise active winds list to be empty ; ADRL R1, activewinds+lh_indicator STR R1, activewinds+lh_forwards [ ChildWindows STR R0, activewinds+lh_indicator | MOV R1, #nullptr STR R1, activewinds+lh_indicator ] ADRL R1, activewinds+lh_forwards STR R1, activewinds+lh_backwards ; ; Initialise old active winds list to be empty ; [ ChildWindows ADRL R1, oldactivewinds+lh_indicator STR R1, oldactivewinds+lh_forwards STR R0, oldactivewinds+lh_indicator ADRL R1, oldactivewinds+lh_forwards STR R1, oldactivewinds+lh_backwards ; ; Initialise opening winds list to be empty ; NB: This must be done BEFORE initrectptrs is first called ; ADRL R1, openingwinds+lh_indicator STR R1, openingwinds+lh_forwards STR R0, openingwinds+lh_indicator ADRL R1, openingwinds+lh_forwards STR R1, openingwinds+lh_backwards ; ; Initialise heldoverwinds to null (this is a singly-linked list) ; STR R0, heldoverwinds ] ; ; reset mouse flags, buttons etc. ; MOV R0,#initdotdash1 STRB R0,dotdash1 MOV R0,#initdotdash2 STRB R0,dotdash2 ; MOV R0,#0 [ ChildWindows STRB R0,openspending ] STRB R0,memoryOK STR R0,menus_temporary ; there aren't any! STR R0,dragtype STR R0,draghandle [ Autoscr STR R0, dragflags STR R0, autoscr_state STR R0, autoscr_handle STR R0, autoscr_pz_x0 STR R0, autoscr_pz_y0 STR R0, autoscr_pz_x1 STR R0, autoscr_pz_y1 STR R0, autoscr_pause STR R0, autoscr_next_t STR R0, autoscr_last_t STR R0, autoscr_last_x STR R0, autoscr_last_y STRB R0, autoscr_scrolling STRB R0, autoscr_pausing ] [ MultiClose STR R0, nextwindowtoiconise ] [ UTF8 STRB R0, keystring_buflen ; all the key buffers are initially empty STRB R0, keyprocess_buflen STRB R0, keyin_buflen STRB R0, keyout_buflen ] STRB R0,dragflag STRB R0,dotdash ; impossible dot-dash pattern ADRL R14,freepoolinuse STRB R0,[R14] STR R0,filehandle STR R0,hotkeyptr ASSERT cf_dormant = 0 STR R0,commandflag STR R0,freepoolpages STR R0,mouseflags STR R0,mousebuttons ; will be copied to oldbuttons [ outlinefont STR R0, systemfont ; font is not claimed currently STR R0, symbolfont ; neither is this one STR R0, currentfont ; and we don't know the current font yet ADRL R14,fontnamebuffer STR R0,[R14] ; ok to use STR, puts 0 in first loc of buffer ] [ NCErrorBox ADRL R14, ptrsuspendflag STR R0, [R14], #4 ASSERT ptrpreserveflag = ptrsuspendflag + 4 STR R0, [R14] ] ; MOV R0,#nullptr STR R0,ptrwindow ; ; MOV R0,#-4 STR R0,menuSP STR R0,menutaskhandle ; MOV R14,#-1 ; invalidate sprite translation stuff STR R14,sprite_lastmode ; ; Braindead panic redraw indication. ; MOV R14,#BPR_notatall STR R14,BPR_indication ; Debug xx,"initptrs; taskcount =",#taskcount ; BL initrectptrs ; Debug xx,"initptrs; taskcount =",#taskcount ; LDR R14,=:INDEX:taskpointers STR R14,taskhandle ; points to task pointer array STR R14,nulltaskhandle ; LDR R0,ptr_DomainId STR R14,[R0] ; for Stuart ; ; initialise message queue and iconbar window ; MOV R14,#nullptr STR R14,backwindowhandle ; created when Wimp_Init called 1st STR R14,errorhandle ; created when Wimp_Init called 1st STR R14,headpointer ; no messages on queue [ NKmessages1 STR R14,lastpointer ] STR R14,iconbarhandle ; no iconbar window STR R14,iconbarleft+icd_list ; no filing system icons STR R14,iconbarright+icd_list ; no accessory icons MOV R14,#0 STR R14,iconbarleft+icd_width ; for later STR R14,iconbarright+icd_width ; SWI XOS_ReadMonotonicTime STR R0,myref ; confuse punter by randomising myref MOV R0,R0,LSL #flag_versionbit ; unset bottom bits STR R0,tasknumber ; global task version number ; Figure out ROM location MOV R0,#ModHandReason_LookupName ADR R1,UtilityModuleName SWI XOS_Module MOVVS R3,#&03800000 ; R3 = address of utility module MOV R3,R3,LSR #20 MOV R3,R3,LSL #20 ; round down to a megabyte (= ROM base, hopefully) CMP R3,#&04000000 ADDLO R4,R3,#8*1024*1024 ; assume 8M ROM if <64M (Arthur-RISC OS 4) ADDHS R4,R3,#64*1024*1024 ; and 64M ROM if base >=64M (RISC OS 5) SUB R4,R4,#1 ; make end inclusive (may be &FFFFFFFF) STR R3,ROMstart STR R4,ROMend ; [ :LNOT: KernelLocksFreePool BL initdynamic ; needs doing on Service_Reset ] ; MOV R0,#ChangeEnvironmentV ADRL R1,ChangeEnvCode ; investigate handler changes BL claim ; Debug xx,"initptrs; taskcount =",#taskcount ; Pull "R0-R11,PC" UtilityModuleName = "UtilityModule", 0 LTORG ; ; set up free pointers for rectangle area ; initrectptrs ROUT Push "R0-R2,LR" ; Debug xx,"initptrs; taskcount =",#taskcount ; ADRL R1,rlinks-4 ; point chain to next item MOV R0,#4 clearrptrs STR R0,[R1,R0] ADD R0,R0,#4 ; 1 word per entry CMP R0,#4*maxrects BCC clearrptrs ; MOV R2,#nullptr ; terminate the list STR R2,[R1,R0] ; Debug xx,"initptrs; taskcount =",#taskcount ; ; set up header links ; ADRL R1,rlinks ADD R2,R1,#firstfreerect MOV R0,#firstfreerect ; freerects is first item clearrlinks STR R0,[R1],#4 MOV R0,#nullptr CMP R1,R2 BCC clearrlinks ; ; rectangle area has been cleared, so openingwinds -> #w_oldwindowrects must be set to NULL ; [ ChildWindows LDR R1,openingwinds + lh_forwards 01 LDR R14,[R1,#ll_forwards] CMP R14,#nullptr MOVNE R14,#nullptr STRNE R14,[R1,#w_oldwindowrects - w_opening_link] LDRNE R1,[R1,#ll_forwards] BNE %BT01 ] ; Debug xx,"initptrs; taskcount =",#taskcount ; Pull "R0-R2,PC" ; ; Initialise called again by the same task - delete any windows owned by it ; That should also remove input focus etc. ; wipewindows ROUT Push "R1,R5-R7,handle,LR" ; LDR R7,taskhandle ; LDR R14,dragtype ; kill dragbox if task is dying TEQ R14,#0 BEQ %FT01 LDR R14,dragtask TEQ R7,R14 BLEQ nodragging 01 LDR R14,menutaskhandle ; kill menus if owner is dying TEQ R7,R14 ; NB menutaskhandle is only an index MOVEQ R0,#-4 ; (no version bits) STREQ R0,menutaskhandle BLEQ closemenus ; ; Start pointing at the link which points at the first window ; ADRL R5,allwinds+lh_forwards-ll_forwards B wipenext wipelp ; If the window being checked isn't owned by the interesting task move onto it and loop LDR R14,[R0,#w_taskhandle-w_all_link] TEQ R14,R7 MOVNE R5,R0 BNE wipenext ; ; Otherwise, delete the next window. ; SUB R0,R0,#w_all_link Debug opn,"**** Deleting task's remaining window",R7,R0 Rel R0,R0 BL int_delete_window wipenext ; If the next window exists, go round to check it for deletion ; LDR R0,[R5,#ll_forwards] LDR R14,[R0,#ll_forwards] CMP R14,#nullptr BNE wipelp ; ; delete any iconbar icons owned by this task ; ADR R1,iconbarleft BL wipeicons ADR R1,iconbarright BL wipeicons ; ; Wimp_CommandWindow (0) will be called when the task exits ; Pull "R1,R5-R7,handle,PC" wipeicons Push "R1-R2,LR" 01 LDR R14,[R1,#icd_list] ; R1 --> head of list LDR R1,taskhandle 02 CMP R14,#nullptr Pull "R1-R2,PC",EQ LDR R2,[R14,#icb_taskhandle] ; R2 = task handle TEQ R2,R1 ; (no version bits internally) LDRNE R14,[R14,#icb_link] BNE %BT02 LDR R2,[R14,#icb_iconhandle] BL int_removefromiconbar LDR R1,[sp,#0*4] B %BT01 ; ; Palette initialisation code ; Entry: R0 --> rest of command line (ie. filename) ; R1 = number of parameters (ie. 1) ; R12 --> module's private word ; Exit: palette read into [paltable] ; recalcpalette is called (sets up palette from settings) ; WimpPalette_Code Push "R1-R12,LR" LDR R12,[R12] ; MOV R1,R0 ; R1 --> filename MOV R0,#OSFind_ReadFile :OR: open_nopath ; already substituted SWI XOS_Find ; MOVVC R1,R0 MOVVC R0,#OSArgs_ReadEXT SWIVC XOS_Args BVS %FT99 ; ; loop, reading each palette entry in turn ; MOV R3,#0 ; colour expected next ADR R5,temppaltable ; Use temp area in case of errors LDR R6,=&F0F0F000 readcolours TEQ R2,#3*20 ; old-style palette BEQ %FT01 ; - has no header bytes TEQ R2,#6*20 ; 16 colour palette? BNE errbadpalfile2 ; No then can't cope so error ; SWI XOS_BGet TEQ R0,#19 ; must be a 19 SWIEQ XOS_BGet TEQEQ R0,R3 ; must be the next colour SWIEQ XOS_BGet TEQEQ R0,#16 ; must be a 16 BNE errbadpalfile 01 SWI XOS_BGet ORRVC R4,R3,R0,LSL #8 ; red SWIVC XOS_BGet ORRVC R4,R4,R0,LSL #16 ; green SWIVC XOS_BGet ORRVC R4,R4,R0,LSL #24 ; blue ; ANDVC R4,R4,R6 ORRVC R4,R4,R4,LSR #4 ; guff with it to make it usable ; BVS errbadpalfile ; STR R4,[R5,R3,LSL #2] ADD R3,R3,#1 CMP R3,#16 BCC readcolours ; All well so far, so copy temppaltable to paltable MOV R3, #16 ADR R4, temppaltable ADRL R5, paltable 01 LDR LR, [R4],#4 STR LR, [R5],#4 SUBS R3,R3,#1 BNE %BT01 ; ; the next 4 colours are the border colour and mouse colours ; these are just set up as they are, with no regard to preferences ; MOV R3,#4 ADRL R5,othercolours colourlp2 TEQ R2,#3*20 ; old-style palette BEQ %FT01 ; SWI XOS_BGet ; 19 SWIVC XOS_BGet ; 0 / 1..3 SWIVC XOS_BGet ; 24 / 25 01 SWIVC XOS_BGet MOVVC R4,R0,LSL #8 ; red SWIVC XOS_BGet ORRVC R4,R4,R0,LSL #16 ; green SWIVC XOS_BGet ORRVC R4,R4,R0,LSL #24 ; blue BVS errbadpalfile ; STR R4,[R5],#4 SUBS R3,R3,#1 BNE colourlp2 ; continue until all mouse colours done ; MOV R0,#OSArgs_EOFCheck SWI XOS_Args BVS errbadpalfile TEQ R2,#0 ; must have EOF at this point! BEQ errbadpalfile ; MOV R0,#0 ; close file SWI XOS_Find ; BL recalcpalette ; LDR R14,taskcount ; if we're running, CMP R14,#0 LDRNE R14,log2bpp ; and in 256-colour mode, CMPNE R14,#3 MOVNE cx0,#-bignum MOVNE cy0,#-bignum MOVNE cx1,#bignum MOVNE cy1,#bignum BLNE markinvalid_cx0cy0cx1cy1 99 Pull "R1-R12,PC" errbadpalfile MOV R0,#0 SWI XOS_Find MyXError WimpBadPalFile B %BT99 MakeErrorBlock WimpBadPalFile errbadpalfile2 MOV R0,#0 SWI XOS_Find MyXError WimpBadPalFile2 B %BT99 MakeErrorBlock WimpBadPalFile2 ; ; Recalculate colour mappings based on [log2bpp] and [paltable] ; Set up the low bytes of the palette entries to indicate actual colour used ; If Font Manager present, font fg/bg colours are also set up ; NB: palette itself is not reprogrammed unless Wimp is currently active ; but logical colour mapping is always reprogrammed ; recalcpalette Push "R1-R5,R10,LR" ; LDR R14,commandflag ; this can be called without Wimp_Init Push "R14" ORR R14,R14,#cf_suspended STR R14,commandflag ; BL readvduvars ; just in case ; SWI XColourTrans_InvalidateCache ; [ false ; this stuff gets done in Service_InvalidateCache MOV R14,#-1 ; sprite stuff is now invalid (as is ColourTrans's cache) STR R14,sprite_lastmode LDR R2,pixtable_at TEQ R2,#0 ; pixtable currently claimed? MOVNE R0,#ModHandReason_Free BLNE XROS_Module ; attempt to free up the workspace ; MOV R2,#0 STR R2,pixtable_at ; mark block as released ] ; ; first set up border & mouse colours ; LDR R14,taskcount TEQ R14,#0 BEQ donepal ; finished and setup the palette ; MOV R3,#0 ; include border colour BL setmousepalette ; set up mouse (& border) palette ; LDR R2,log2bpp ; get the Log2BPP of the mode CMP R2,#3 BHS setpalette_finished ; CMP R2,#1 [ False ; Prior to v310 ADRLOL R3,transtable1 ; R3 -> translation table 1BPP ADREQL R3,transtable2 ; 2BPP ADRHIL R3,transtable4 ; 4BPP | ; Always use default mappings ADRLOL R3,map1bpp ; R3 -> translation table 1BPP ADREQL R3,map2bpp ; 2BPP ADRHIL R3,map4bpp ; 4BPP ] ; MOV R14,#1 MOV R2,R14,LSL R2 MOV R2,R14,LSL R2 ; R2 = number of colours to setup ADRL R4,paltable+1 ; R4 -> palette to program from MOV R5,#0 ; R5 = colour being programmed setpalette_loop Push "R1-R3" ; MOV R0,R5 MOV R1,#&10 SWI XOS_ReadPalette ANDVC R2,R2,#&F0 ; get the supremacy bit for that colour ; SWIVC XOS_WriteI +19 MOVVC R0,R5 SWIVC XOS_WriteC ORRVC R0,R2,#&10 SWIVC XOS_WriteC ; 19,colour,16 + supremacy ; Pull "R1-R3" ; and then restore stashed registers ; LDRVCB R14,[R3,R5] ADDVC R0,R4,R14,LSL #2 ; R0 -> palette data MOVVC R1,#3 SWIVC XOS_WriteN ; &RR &GG &BB BVS donepal ADD R5,R5,#1 TEQ R5,R2 BNE setpalette_loop ; loop back until palette programmed setpalette_finished BL defaultfontcolours ; setup the default font colours donepal Pull "R14" STR R14,commandflag ; SavePSR R2 MOV R1,#Service_WimpPalette ; inform palette utility SWI XOS_ServiceCall RestPSR R2,,f ; restore error state ; Pull "R1-R5,R10,PC" ; ; Entry: R3 = 0 or 1 (do / don't program border colour) ; Exit: mouse (& border) palette programmed ; setmousepalette Push "R10,LR" ; ADRL R10,othercolours ADD R10,R10,R3,LSL #2 ; skip border colour if not required ADD R4,R3,#24 ; R4 starts at 24 or 25 01 SWIVC XOS_WriteI+19 MOVVC R0,R3 ; 0 / 1..3 SWIVC XOS_WriteC MOVVC R0,R4 ; 24 / 25 SWIVC XOS_WriteC ADDVC R0,R10,#1 MOVVC R1,#3 SWIVC XOS_WriteN ; r,g,b Pull "R10,PC",VS ADD R10,R10,#4 MOV R4,#25 ADD R3,R3,#1 CMP R3,#4 BCC %BT01 ; Pull "R10,PC" ; ; setfontcolours: ; Entry: R1,R2 = desired background/foreground colours ; Exit: Font_SetFontColours called with appropriate R3 ; SWIWimp_SetFontColours MyEntry "SetFontColours" BL setfontcolours ; doesn't return errors B ExitWimp [ TrueIcon1 ; set font colours (no translation) settruefontcolours Push "R0-R3, LR" B %FT20 ] defaultfontcolours MOV R1,#0 ; background colour MOV R2,#7 ; foreground colour ; convert the logical to physical colours and then call ColourTrans to perform the conversion ; and set the Font Manager setfontcolours Push "R0-R3, LR" BL getpalpointer TraceK fcol, "setfontcolours: WIMP colours bg " TraceD fcol, R1 TraceK fcol, ", fg " TraceD fcol, R2 TraceNL fcol [ TrueIcon1 LDR R1, [R14, R1, LSL #2] ; R1 = physical background colour LDR R2, [R14, R2, LSL #2] ; R2 = physical foreground colour 20 MOV R0, #0 ; do not change current font | MOV R0, #0 ; do not change current font LDR R1, [R14, R1, LSL #2] ; R1 = physical background colour LDR R2, [R14, R2, LSL #2] ; R2 = physical foreground colour ] MOV R3, #14 ; R3 = use as many levels to set the colours TraceK fcol, "setfontcolours: true colours bg " TraceX fcol, R1 TraceK fcol, ", fg " TraceX fcol, R2 TraceNL fcol [ :LNOT:NoFontBodge SWI XColourTrans_SetFontColours STRVS R0, [SP] ] Pull "R0-R3, PC" ;;----------------------------------------------------------------------------- ;; Force_Redraw - mark specified region invalid - will be redrawn later ;; Entry: R0 = window handle (if -1, then consider whole screen) ;; R1-R4 = x0,y0,x1,y1 - box to make invalid ;; or: R0 = window handle ;; R1 = "TASK" ;; R2 = border icon to redraw (3 => title bar, others reserved) ;;----------------------------------------------------------------------------- SWIWimp_ForceRedraw MyEntry "ForceRedraw" BL checkredrawhandle [ ChildWindows BL int_flush_opens ; it's too complicated - wimp out for now! | BVS ExitWimp ; this is pointless ] ; MOV handle,R0 ; now only -1 => redraw whole screen CMP handle,#-1 ; (-2 => redraw icon bar) BEQ markscreeninvalid ; BL checkhandle_iconbar BVS ExitWimp ; [ ChildWindows LDR R14,taskidentifier TEQ R1,R14 ; watch out for the 'special' value MOVEQ R14,#0 ; ensure <> "TASK" STREQ R14,[sp,#0*4] ; and store where it will be reloaded into R1 BEQ force_redraw_special ] Push "R1-R4" Pull "x0,y0,x1,y1" BL int_force_redraw B ExitWimp int_force_redraw Push "LR" BL int_update_window3 ; don't set any flags BLVC markinvalidrects ; old Wimp has already done it BLVC losewindowrects ; waste not, want not! Pull "PC" markscreeninvalid Push "R1-R4" Pull "cx0,cy0,cx1,cy1" BL markinvalid_cx0cy0cx1cy1 B ExitWimp [ ChildWindows force_redraw_special TEQ R2, #0 BEQ int_force_redraw_whole_border CMP R2,#1 [ IconiseButton RSBHSS R14,R2,#8 | RSBHSS R14,R2,#7 ] MOVHS R0,R2 ; ignore all values except 1 to 7 BLHS int_force_redraw_border B ExitWimp int_force_redraw_whole_border ; redraw all of border, including 1-pixel borders MOV R0, #borderrects BL loserects ; clear these lists BL losewindowrects ; - just in case ADD R0, handle, #w_old_wax0 BL oldvisibleportion ; windowrects = visible rectangles of work area LDR R0, rlinks + borderrects LDR R1, rlinks + windowrects STR R0, rlinks + windowrects STR R1, rlinks + borderrects ; store those safely away in borderrects BL oldvisibleouterportion ; windowrects = visible rectangles of whole window MOV R0, #windowrects MOV R1, #borderrects BL subrects ; windowrects -= "borderrects" MOV R1, #wf_inborder BL oldsubtract_children ; subtract furniture windows from windowrects BL markinvalidrects ; add windowrects to invalid list MOV R0, #borderrects BL loserects BL losewindowrects ; clear the lists again B ExitWimp ;.............................................................................. ; In R0 = border icon number ; handle -> window definition ; Out old visible portion of relevant border icon invalidated ; R0,R1,x0,y0,x1,y1 corrupted ; Note that this routine must NOT be called within int_flush_opens, after we've copied invalidrects to oldinvalidrects int_force_redraw_border Entry LDR R1,[handle,#w_old_flags] ASSERT wf_icon1 = 1 :SHL: 24 MOV R14,#1 :SHL: 23 [ IconiseButton TST R1, #ws_open ; was the window open? EXIT EQ TEQ R0, #8 BNE %FT01 TST R1, R14, LSL #2 ; was iconise enabled? LDRNEB R14, iconisebutton TEQNE R14, #0 EXIT EQ LDR R14, [handle, #w_parent] CMP R14, #-1 EXIT NE B %FT02 01 TST R1, R14, LSL R0 ; was this icon enabled? EXIT EQ 02 | TST R1,R14,LSL R0 ; was this icon enabled? TSTNE R1,#ws_open ; and was the window open? EXIT EQ ] ADD R14,handle,#w_old_x0 LDMIA R14,{cx0,cy0,cx1,cy1} BL calc_w_iconposn_R1 ; get OLD icon position Debug opn,"int_force_redraw_border",R0,x0,y0,x1,y1 BL oldvisibleportion_x0y0x1y1 MOV R1,#wf_inborder BL oldsubtract_children ; clip out child windows that could overlap the title bar [ debug Push "handle,userblk" SetRectPtrs LDR R1,[rectlinks,#windowrects] CMP R1,#nullptr BNE %FT01 Debug opn,"**** int_force_redraw_border clipped out" B %FT02 01 getxy R1,cx,cy Debug opn,"int_force_redraw_border first rectangle:",cx0,cy0,cx1,cy1 02 Pull "handle,userblk" ] BL markinvalidrects ; we can do this either during int_flush_open, or after int_flush_opens has finished BL losewindowrects EXIT ] ;;----------------------------------------------------------------------------- ;; Create_Window - set up window definition from parameter block ;;----------------------------------------------------------------------------- SWIWimp_CreateWindow MyEntry "CreateWindow" ; BL int_create_window B ExitWimp int_create_window Push "LR" crw2 LDR R3,[userblk,#w_nicons-w_cw0+u_cw0] MOVS R3,R3,ASL #i_shift ; i_size = 2^i_shift BMI crwerror2 MOVEQ R2,#nullptr BLNE claimblock DebugE crw,"No RMA for icons" BVS crwerror2 MOV R4,R2 MOV R3,#w_size BL claimblock BVC crw3 DebugE crw,"No RMA for window" MOVS R2,R4 ;free first allocated block and return error MOVPL R0,#ModHandReason_Free BLPL XROS_Module B crwerror2 ; Both window blocks allocated - Attach icon block to window block crw3 MOV handle, R2 STR R4,[handle,#w_icons] ; Copy window information into window block MOV R14,userblk ADD R2,handle,#w_cw0 ADD R3,handle,#w_cw1 ; NK: don't go beyond create block crw4 LDR R0,[R14],#4 STR R0,[R2],#4 CMP R2,r3 BLO crw4 ; Copy icon information into icon block LDR R3,[userblk,#w_nicons-w_cw0+u_cw0] TEQ R3,#0 BEQ crw5e ADD R3,R4,R3,ASL #i_shift crw5 LDR R0,[R14],#4 STR R0,[R4],#4 CMP R4,r3 BLO crw5 crw5e LDR R14, createwindowtaskhandle CMP R14, #0 LDRGT R14, taskhandle STR R14, [handle, #w_taskhandle] [ ChildWindows ASSERT lh_forwards=0 :LAND: lh_indicator=4 :LAND: lh_backwards=8 ADD R2,handle,#w_children + lh_indicator MOV R3,#nullptr ADD R4,handle,#w_children + lh_forwards ADD R14,handle,#w_children STMIA R14,{R2-R4} STR R3,[handle,#w_parent] ; default to top-level when opening ADD R2,handle,#w_old_children + lh_indicator MOV R3,#nullptr ADD R4,handle,#w_old_children + lh_forwards ADD R14,handle,#w_old_children STMIA R14,{R2-R4} STR R3,[handle,#w_old_parent] STR R3,[handle,#w_oldwindowrects] MOV R14,#0 STR R14,[handle,#w_alignflags] ; all alignment flags default to zero STR R14,[handle,#w_old_flags] STR R14,[handle,#w_opening_link + ll_forwards] ; not on the list of opening windows ] [ CnP MOV R14, #nullptr STR R14, [handle, #w_seldata] ; no icon contains a selection ] ; Window is now completely valid ; Make guard word valid LDR R14,=w_guardword_valid STR R14,[handle,#w_guardword] ; attach window block to windows list: ; R14 is forwards of header ; R0 is link-link address in header ; so: ; R14 is forwards of handle ; R0 is backwards of handle ; link in handle (address stored in R3) is forwards of R0 and backwards of R14 ADRL R0,allwinds+lh_forwards-ll_forwards ADD R3,handle,#w_all_link LDR R14,[R0,#ll_forwards] STR R14,[R3,#ll_forwards] STR R0,[R3,#ll_backwards] STR R3,[R0,#ll_forwards] STR R3,[R14,#ll_backwards] ; ; in case window starts off toggled, make up some reasonable bhandle bits ; ADD R14,handle,#w_wax0 LDMIA R14,{cx0,cy0,cx1,cy1,x0,y0} MOV y1,#nullptr ; bbhandle ADD R14,handle,#w_bwax0 STMIA R14,{cx0,cy0,cx1,cy1,x0,y0,y1} ; ; validate flag settings & set up upper bits (for compatibility) ; BL bodgewindowflags MOV R0,#nullptr STR R0,[handle,#w_bhandle] ; no window above it ; LDR R14,singletaskhandle CMP R14,#nullptr MOVNE R14,#0 STRNE R14,[handle,#w_minx] ; they meant 0 really! ASSERT w_miny=w_minx+2 ; ; check that work area extent is reasonable ; ADD R14,handle,#w_wex0 LDMIA R14,{x0,y0,x1,y1} BL checkextent Pull "PC",VS ; urk - we should really delete the window if this fails! ADD R14,handle,#w_wex0 STMIA R14,{x0,y0,x1,y1} [ Mode22 MOV R14,#0 STR R14,[handle,#w_origflags] ; for automatic scroll bars ] ; ; set up window outline from work area and flags (allows Wimp_GetWindowOutline to be called) ; [ ChildWindows ADD R1,handle,#w_wax0 LDMIA R1,{x0,y0,x1,y1} BL calc_w_x0y0x1y1 ; calculate x0,y0,x1,y1 ADD R1,handle,#w_x0 STMIA R1,{x0,y0,x1,y1} ; ; copy all window data (makes it easier to check that old window data is correct) ; ASSERT (w_old_end - w_old_parent ) = 13*4 ASSERT handle = R10 ADD R14,handle,#w_parent ; copy from new data to old ADD R9, handle,#w_old_parent LDMIA R14!,{R0-R6} STMIA R9!, {R0-R6} ; copy first 7 words LDMIA R14!,{R0-R5} STMIA R9!, {R0-R5} ; then the next 6 words ] ; ; return handle of window to the user ; Rel R0,handle [ debug LDR R14,[handle,#w_opening_link+ll_forwards] Debug crw,"Window created with handle/opening_link",R0 ] Pull "PC" ; ; if top bit of flags not set, compute flag settings from old-style flags ; bodgewindowflags Push "LR" [ ChildWindows LDRB R14,[handle,#w_tfcol] ; if title fg colour=255 ... TEQ R14,#&FF LDRNE R14,[handle,#w_flags] ; ... cancel all border bits BNE %FT01 LDR R14,[handle,#w_taskhandle] ; but only if task doesn't know about Wimp 3.80 CMP R14,#0 MOVLE R14,#380 ; treat the system task as knowing what to do LDRGT R14,[wsptr,R14] LDRGT R14,[R14,#task_wimpver] CMP R14,#380 LDR R14,[handle,#w_flags] BICLT R14,R14,#wf_iconbits BICLT R14,R14,#wf_title:OR:wf_vscroll:OR:wf_hscroll:OR:wf_nobackquit 01 | LDRB R14,[handle,#w_tfcol] ; if title fg colour=255 ... TEQ R14,#&FF LDR R14,[handle,#w_flags] ; ... cancel all border bits BICEQ R14,R14,#wf_iconbits BICEQ R14,R14,#wf_title:OR:wf_vscroll:OR:wf_hscroll:OR:wf_nobackquit ] TST R14,#wf_newformat BICEQ R14,R14,#wf_iconbits ; cancel 'other' bits BICNE R14,R14,#wf_title:OR:wf_vscroll:OR:wf_hscroll:OR:wf_nobackquit TST R14,#wf_title ORRNE R14,R14,#wf_icon1:OR:wf_icon2:OR:wf_icon3 TST R14,#wf_nobackquit BICNE R14,R14,#wf_icon1:OR:wf_icon2 TST R14,#wf_vscroll ORRNE R14,R14,#wf_icon4 TST R14,#wf_vscroll ORRNE R14,R14,#wf_icon5 TST R14,#wf_vscroll:OR:wf_hscroll ORRNE R14,R14,#wf_icon6 TST R14,#wf_hscroll ORRNE R14,R14,#wf_icon7 ; TST R14,#wf_icon3 BICEQ R14,R14,#wf_icon1:OR:wf_icon2 TST R14,#wf_icon3:OR:wf_icon5 BICEQ R14,R14,#wf_icon4 TST R14,#wf_icon5:OR:wf_icon7 BICEQ R14,R14,#wf_icon6 ; BIC R14,R14,#ws_system ; user can't set these bits STR R14,[handle,#w_flags] ; (closed and not top window) ; Pull "PC" crwerror2 MyXError WimpTooBig Pull "PC" MakeErrorBlock WimpTooBig LTORG ;;---------------------------------------------------------------------------- ;; Set_Extent - allows the user to alter the work area extent ;; Entry: R0 = window handle ;; R1 --> block: x0,y0,x1,y1 (new extent) ;; Checks that the new work area is outside the current window settings ;;---------------------------------------------------------------------------- SWIWimp_SetExtent MyEntry "SetExtent" Debug err,"Wimp_SetExtent task,handle",#taskhandle,R0 MOV handle,R0 BL checkhandle_owner ; window must be owned by task BVS ExitWimp LDMIA userblk,{x0,y0,x1,y1} BL checkextent ADDVC R14,handle,#w_wex0 STMVCIA R14,{x0,y0,x1,y1} [ togglebits ; Oops - calctoggle tramples on ws_toggling and ws_toggled2 LDRVC R1, [handle, #w_flags] BLVC calctoggle ; calls int_force_redraw_border if toggle bit changes LDRVC R14, [handle, #w_flags] BICVC R14, R14, #ws_toggling :OR: ws_toggled2 ANDVC R1, R1, #ws_toggling :OR: ws_toggled2 ORRVC R14, R14, R1 STRVC R14, [handle, #w_flags] | BLVC calctoggle ; calls int_force_redraw_border if toggle bit changes ] [ ChildWindows MOVVC R0,#5 BLVC int_force_redraw_border ; redraw vertical scrollbar (if present) MOVVC R0,#7 BLVC int_force_redraw_border ; redraw horizontal scrollbar (if present) | LDRVC x0,[handle,#w_wax1] ; vertical scroll bar LDRVC y0,[handle,#w_way0] LDRVC x1,[handle,#w_x1] LDRVC y1,[handle,#w_y1] ; (including toggle box) BLVC visibleportion_x0y0x1y1 BLVC markinvalidrects LDRVC x0,[handle,#w_wax0] ; horizontal scroll bar LDRVC y0,[handle,#w_y0] LDRVC x1,[handle,#w_wax1] LDRVC y1,[handle,#w_way0] BLVC visibleportion_x0y0x1y1 BLVC markinvalidrects ] BLVC recalcdrag ; if window is being dragged B ExitWimp ;............................................................................. ; Ensure window extent is not smaller than the minimum window size! ; In x0,y0,x1,y1 = new extent of window ; handle -> window data (ie. absolute handle of window) ; Out x0,y0,x1,y1 updated if necessary ; [handle,#w_flags] :AND: ws_onscreenonce set checkextent Push "cx0,cy0,cx1,cy1,LR" ; BL minwindowx Pull "cx0,cy0,cx1,cy1,PC",VS SUB R1,x1,x0 CMP R1,R14 ADDLT x1,x0,R14 BL minwindowy Pull "cx0,cy0,cx1,cy1,PC",VS SUB R1,y1,y0 CMP R1,R14 SUBLT y0,y1,R14 ; round all coordinates to a whole number of pixels LDR R14,dx_1 BIC x0,x0,R14 BIC x1,x1,R14 LDR R14,dy_1 BIC y0,y0,R14 BIC y1,y1,R14 ; set ws_onscreenonce, so that next OpenWindow keeps it on screen ; only do this if the window is currently entirely on-screen Push "x0,y0,x1,y1" ADD R14,handle,#w_x0 LDMIA R14,{cx0,cy0,cx1,cy1} ADR R14,scrx0 LDMIA R14,{x0,y0,x1,y1} CMP cx0,x0 CMPGE cy0,y0 CMPGE x1,cx1 CMPGE y1,cy1 LDRGE R14,[handle,#w_flags] ORRGE R14,R14,#ws_onscreenonce STRGE R14,[handle,#w_flags] Pull "x0,y0,x1,y1" CLRV ; return error if none of window is visible (disabled normally) [ debugextent ADD R14,handle,#w_wax0 ; work out visible region LDMIA R14!,{cx0,cy0,cx1,cy1} SUB cx1,cx1,cx0 ; width SUB cy0,cy1,cy0 ; height LDMIA R14,{cx0,cy1} ; scroll offsets (top-left) ADD cx1,cx0,cx1 SUB cy0,cy1,cy0 ; CMP x0,cx0 CMPLE y0,cy0 CMPLE cx1,x1 CMPLE cy1,y1 ; MyXError WimpBadExtent,GT ] Pull "cx0,cy0,cx1,cy1,PC" [ debugextent MakeErrorBlock WimpBadExtent ] ;;---------------------------------------------------------------------------- ;; Create_Icon - adds icon definition to those in the specified window ;; - must look for a deleted icon in the list first ;;---------------------------------------------------------------------------- SWIWimp_CreateIcon MyEntry "CreateIcon" ; LDR handle,[userblk] CMP handle,#-8 BHS addtoiconbar ; handle = -1 - -8 BL checkhandle_owner ; check that window is owned! BLVC int_create_icon B ExitWimp int_create_icon Push "LR" ; LDR R2,[handle,#w_nicons] LDR R0,[handle,#w_icons] ADD R2,R0,R2,ASL #i_shift ; end of icon list MOV R3,#0 ; icon number crilp CMP R0,R2 ; reached end? BCS addicon LDR R14,[R0,#i_flags] TST R14,#is_deleted ADDEQ R3,R3,#1 ADDEQ R0,R0,#i_size BEQ crilp ; copyicon ASSERT i_size=32 Push "R1-R9" LDMIA userblk,{R1-R9} ; first word is unused STMIA R0,{R2-R9} Pull "R1-R9" ; MOV R0,R3 ; R0 = icon handle (0..n-1) [ RO4 ; MB added call here to force update of pointer shape if an icon is created under the pointer bl update_pointer_shape_for_icon_create ; end MB ] Pull "PC" addicon Push "R3" LDR R2,[handle,#w_icons] CMP R2, #nullptr ; R1 = offset into icons block of place to put new icon MOVEQ R1, #0 MOVEQ R0, #ModHandReason_Claim SUBNE R1,R0,R2 MOVNE R0,#ModHandReason_ExtendBlock MOV R3,#i_size BL XROS_Module STRVC R2,[handle,#w_icons] ; Convert R1 back into an address ADDVC R0,R1,R2 Pull "R3" Pull "PC",VS ; ADD R14,R3,#1 ; update no. of icons STR R14,[handle,#w_nicons] B copyicon [ RO4 ; MB new routine to check if the new icon is being created under the pointer and set up the pointe shape if needed update_pointer_shape_for_icon_create ROUT Push "r5,x0-y1,lr" LDR x0,[handle,#w_scx] LDR y0,[handle,#w_scy] LDR x1,[handle,#w_wax0] LDR y1,[handle,#w_way1] SUB x0,x0,x1 ; x0 = scroll x - min x SUB y0,y0,y1 ; y0 = scroll y - max y LDR r5,mousexpos LDR lr,mouseypos ADD r5,r5,x0 ADD lr,lr,y0 ADD x0,userblk,#4 LDMIA x0,{x0-y1} CMP r5,x0 CMPGE lr,y0 Pull "r5,x0-y1,pc",LT CMP r5,x1 CMPLT lr,y1 Pull "r5,x0-y1,pc",GE ; pointer is over the new icon LDR R5,mouseflags TST R5,#mf_wait2clicks ; reset pointer shape if nec. BLNE doubleptr_off BIC R5,R5,#mf_pendingexceptdrag ; cancel pending (except drag) STR R5,mouseflags LDR r5,[userblk,#i_flags + 4] TST r5,#if_text TSTNE r5,#if_indirected ; Is it indirected text ? Pull "r5,x0-y1,pc",EQ Push "r0-r4" MOV r2,#WimpValidation_Pointer LDR r3,[userblk,#i_data+4 + 4] ; Pointer to validation string. CMP r3,r3,ASR #31 Pull "r0-r5,x0-y1,pc",EQ BL findcommand Pull "r0-r5,x0-y1,pc",NE ADRL r2,pointer_sprite 01 LDRB R14,[r3],#1 CMP R14,#"," MOVEQ R14,#-1 CMP R14,#";" MOVEQ R14,#0 CMP R14,#" " STRGTB r14,[r2],#1 BGT %BT01 MOV R4,#0 ; Default active point is 0,0 MOV R5,#0 STRB R4,[r2] ; Terminate the sprite name. CMP R14,#-1 BNE %FT02 BL getnumber MOV R4,R0 ; Returns 0 if not found. LDRB R14,[R3],#1 CMP R14,#"," BNE %FT02 BL getnumber MOV R5,R0 ; Returns 0 if not found. 02 MOV R0,#SpriteReason_SetPointerShape ADRL R2,pointer_sprite MOV R3,#1 [ Autoscr LDR R14, autoscr_state ; don't reprogram pointer if autoscrolling is enabled TST R14, #af_enable ORRNE R3, R3, #&10 ] MOV R6,#0 MOV R7,#0 SWI XWimp_SpriteOp ; take from Wimp's sprite area(s) MOV R14,#-1 ADRL R1,special_pointer STR R14,[r1] Pull "r0-r5,x0-y1,pc" ] ; Handy routine for the menu code in Wimp05 to avoid RMA hammering ; On entry: R3 = number of icons ; On exit : R2 = first icon allocated (VC); memory alloc failure if VS int_create_multiple_icons Push "R3,LR" LDR R2,[handle,#w_icons] CMP R2, #nullptr MOVEQ R0, #ModHandReason_Claim MOVNE R0, #ModHandReason_ExtendBlock MOV R3, R3, LSL #i_shift BL XROS_Module Pull "R3,PC",VS STR R2,[handle,#w_icons] Pull "R3" LDR R0,[handle,#w_nicons] ADD R2,R2,R0,LSL #i_shift ; return first icon address ADD R0,R0,R3 STR R0,[handle,#w_nicons] Pull "PC" ;;----------------------------------------------------------------------------- ;; Delete_Window - delete the definition of a window and free the space ;; Entry: [userblk] = window handle (relative) ;; R0 = handle if calling internal entry point ;;----------------------------------------------------------------------------- SWIWimp_DeleteWindow MyEntry "DeleteWindow" ; LDR R0,[userblk] MOV handle,R0 BL checkhandle_owner ; only done when SWI entry called BVS ExitWimp ; Push "R0-R2" LDR R2,[userblk] ; iconify a window - broadcast the message about Window deleted ; MOV R14,#ms_data+4 STR R14,[sp,#-(ms_data+4)]! ; MOV R0,#User_Message ; broadcasting a user message MOV R1,sp STR R2,[R1,#ms_data] ; data = window handle MOV R2,#0 STR R2,[R1,#ms_yourref] ; no your ref ; LDR R14,=Message_WindowClosed STR R14,[R1,#ms_action] ; BL int_sendmessage_fromwimp ADD sp,sp,#(ms_data+4) Pull "R0-R2" ; correct stack and then restore registers ; BL int_delete_window ; B ExitWimp [ ChildWindows LTORG ; we need one of these sometime! ] int_delete_window Push "R1-R9,LR" Debug crw,"Deleting window",R0 ; BL byemessages ; R0 = window handle ; don't deliver messages for this one MOV handle,R0 BL checkhandle BLVC nocaret ; R0,handle = rel/abs handles Pull "R1-R9,PC",VS ; LDR R14,pending_window TEQ R14,R0 BNE %FT01 LDR R7,mouseflags TST R7,#mf_wait2clicks ; reset pointer shape if nec. BLNE doubleptr_off BIC R7,R7,#mf_pending STR R7,mouseflags 01 ; If window has active icon then attempt to release it - fixes address exception on window deleetion LDR R14,border_windowselected TEQ R14,handle MOVEQ R14,#nullptr STREQ R14,border_iconselected STREQ R14,border_windowselected Push "R0" ; relative handle BL int_close_window Pull "R1" ; R1 = relative handle Pull "R1-R9,PC",VS ; preserve R0 ; ; close the window's children (so we can delete it once we've flushed the opens) ; [ ChildWindows Push "handle" LDR handle,[handle,#w_children + lh_forwards] 02 ASSERT ll_forwards = 0 LDR R14,[handle],#-w_active_link CMP R14,#nullptr BEQ %FT03 BL int_close_window ; must call this so we get the child window on the 'opening' list LDR handle,[handle,#w_active_link + ll_forwards] B %BT02 03 Pull "handle" ; ; For now we just call int_flush_opens to ensure that the window isn't on the oldactivewinds list ; TODO: a more sophisticated method would be to defer the discarding of the window block until the next call of int_flush_opens ; BL int_flush_opens ; remove from old window list ] ; ; Delink window from all-winds list ; LDR R14,[handle,#w_all_link+ll_forwards] LDR R0,[handle,#w_all_link+ll_backwards] STR R14,[r0,#ll_forwards] STR R0,[R14,#ll_backwards] ; Throw it away MOV R2,handle BL discard_window ; Debug crw,"Window deleted" Pull "R1-R9,PC" ;----------------------------------------------------------------------------- ; Entry : R2 = address of window structure ; Exit : window structure and any items hanging off it are freed, or error ;----------------------------------------------------------------------------- discard_window Push "R0,R2,R3,LR" ; Invalidate window before freeing MOV R14,#nullptr STR R14,[R2,#w_guardword] MOV R3,R2 LDR R2,[R3,#w_icons] CMP R2,#nullptr MOV R0,#ModHandReason_Free BLNE XROS_Module STRVS R0,[R13] MOV R2,R3 MOVVS R3,#0 ; Indicator of earlier error BL XROS_Module ; Soldier on if error freeing icons STRVS R0,[R13] TEQ R3,#0 ; Set error if error earlier SETV EQ Pull "R0,R2,R3,PC" ;;----------------------------------------------------------------------------- ;; Delete_Icon - delete the definition of an icon ;;----------------------------------------------------------------------------- SWIWimp_DeleteIcon MyEntry "DeleteIcon" ; LDR handle,[userblk] LDR R2,[userblk,#4] ; icon handle CMP R2,#nullptr ; ignore null deletes BLE ExitWimp ; (they don't exist anyway) ; CMP handle,#nullptr CMPNE handle,#nullptr2 BEQ removefromiconbar BL checkhandle_owner ; ensure window is owned BLVC int_deleteicon B ExitWimp ; ; Entry: handle --> window definition ; R2 = icon handle ; int_deleteicon Push "R1-R3,R6,LR" MOV R6,handle ; Save window handle ; Rel R0,handle LDR R14,caretdata TEQ R14,R0 LDREQ R14,caretdata+4 TEQEQ R14,R2 ; R2 not null! MOVEQ R0,#nullptr BLEQ int_set_caret_position ; turn off caret if nec. ; MOV handle,R6 ; Restore window handle LDR R3,[handle,#w_nicons] LDR R0,[handle,#w_icons] ADD R0,R0,R2,ASL #i_shift ADD R14,R2,#1 ; compare number of icons up to and including this handle CMP R14,R3 ; with number of icons Pull "R1-R3,R6,PC",HI ; deleted (doesn't exist) LDRLO R14,[R0,#i_flags] ORRLO R14,R14,#is_deleted STRLO R14,[R0,#i_flags] Pull "R1-R3,R6,PC",LO ; ; if an icon is deleted from the end, see if we can delete any more ; MOV R1,#-i_size delilp SUBS R3,R3,#1 BEQ goshuffdel LDR R14,[R0,#-i_size+i_flags] TST R14,#is_deleted SUBNE R0,R0,#i_size ; split address SUBNE R1,R1,#i_size ; amount to shuffle by BNE delilp goshuffdel STR R3,[handle,#w_nicons] ; no. of icons left MOV R0,#ModHandReason_ExtendBlock LDR R2,[handle,#w_icons] MOV R3,R1 BL XROS_Module STRVC R2,[handle,#w_icons] ; Will store -1 if reduced to 0 size Pull "R1-R3,R6,PC" ;;----------------------------------------------------------------------------- ;; Open_Window - bring window to the front at the specified position/size ;;----------------------------------------------------------------------------- SWIWimp_OpenWindow MyEntry "OpenWindow" [ ChildWindows LDR R14,openidentifier1 TEQ R2,R14 ; watch out for the 'special' value MOVEQ R14,#0 ; ensure <> "TASK" STREQ R14,[sp,#1*4] ; and store where it will be reloaded into R2 CMP userblk,userblk,ASR #31 ; If R1=0 or -1 on entry, just flush the pending opens BEQ doflush BL int_open_window ; child windows can be opened by a task other than the owner B ExitWimp doflush BL int_flush_opens B ExitWimp | LDR handle,[userblk,#u_handle] BL checkhandle_owner ; only check this when SWI entry called BLVC int_open_window B ExitWimp ] [ ChildWindows MakeErrorBlock WimpBadParent openidentifier1 DCB "TASK" ; for new-style opens ] ; New version attempts to buffer coordinate changes and do all the invalidation/copying together at the end ; It also performs auto-aligning of parents and children, and attempts to combine movements of parent and child windows int_open_window Push "LR" BL checkredrawhandle ; we're going to destroy rectangles! [ :LNOT: ChildWindows LDRVC handle,[userblk,#u_handle] BLVC checkhandle ; handle -> window block | CheckAllWindows "int_open_window (before)" LDR handle,[userblk,#u_handle] BL checkhandle_iconbar ; handle -> window block (allow direct opening of iconbar) Pull "PC",VS ; note that int_close_window calls int_start_opens, and we call int_close_window from within int_open_window LDR R14,openidentifier1 TEQ R2,R14 LDRNE R3,[handle,#w_parent] ; keep same parent LDRNE R4,[handle,#w_alignflags] ; and alignment flags BNE %FT01 CMP R3,#nullptr BEQ %FT06 ; top-level window ; validate parent handle now (and make it absolute) Push "handle" MOV handle,R3 [ false BL checkhandle_iconbar ; yes, you can open windows inside the iconbar! | BL checkhandle ; no, you can't any more ] MOVVC R3,handle Pull "handle" Pull "PC",VS ; check that the proposed parent is not itself a child (or grandchild etc.) of this window MOV R14,R3 05 CMP R14,handle MyXError WimpBadParent,EQ ; can't nest a window inside itself Pull "PC",VS LDR R14,[R14,#w_parent] CMP R14,#nullptr ; check parent's parent (etc.) BNE %BT05 ; check for window flags being altered by the caller 06 TST R4,#alf_setflags BEQ %FT01 BIC R4,R4,#alf_setflags ; never set this in the actual alignment flags LDR R5,[handle,#w_flags] ; R5 = existing flags LDR R14,[userblk,#u_flags] STR R14,[handle,#w_flags] ; stick new ones in BL bodgewindowflags ; resolve old/new border flag settings [ oops - this destroys the ws_system flags ] LDR R14,[handle,#w_flags] BIC R14,R14,#ws_system AND R5,R5,#ws_system ; now restore the old status flags that were clobbered by bodgewindowflags ORR R14,R14,R5 STR R14,[handle,#w_flags] 01 STR R3,newparent ; absolute handle STR R4,newalignflags ] [ debug LDR R14,[userblk,#u_bhandle] Debug opn,"Opening window,parent,behind:",handle,R3,R14 ] BLVC calc_w_status ; find out window above us Pull "PC",VS [ Mode22 LDR R0,[handle,#w_origflags] LDR R14,[handle,#w_flags] TEQ R0,#0 STREQ R14,[handle,#w_origflags] ] ; LDR R0,[handle,#w_taskhandle] ; A system window ? CMP R0,#0 BLE %FT01 ; Yes, skip. LDR R0,[wsptr,R0] ; Get task pointer. LDR R14,[R0,#task_windows] ADD R14,R14,#1 STR R14,[R0,#task_windows] ; Now has one more window. LDR R14,[R0,#task_priority] ORR R14,R14,#priority_windows ; Set priority to reflect it. STR R14,[R0,#task_priority] 01 LDR R0,[userblk,#u_handle] LDR R14,[userblk,#u_bhandle] TEQ R14,R0 ; if opening behind itself LDREQ R0,[handle,#w_bhandle] STREQ R0,[userblk,#u_bhandle] ; keep in same posn in stack CMP R14,#-3 ; Opening behind backdrop ? BNE %FT01 LDR R14,[handle,#w_flags] TST R14,#ws_hasfocus MOVNE R0,#-1 SWINE XWimp_SetCaretPosition ; Must call SWI, to prevent task switch. Pull "PC",VS 01 ; ; round coords in user block to multiples of dx,dy ; ADD R14,userblk,#u_wax0 LDMIA R14,{cx0,cy0,cx1,cy1,x0,y0} LDR R14,dx_1 BIC cx0,cx0,R14 BIC cx1,cx1,R14 BIC x0,x0,R14 LDR R14,dy_1 BIC cy0,cy0,R14 BIC cy1,cy1,R14 BIC y0,y0,R14 ; ; check that size is within the specified min/max window size ; LDR x1,[handle,#w_wex1] LDR y1,[handle,#w_wex0] SUB x1,x1,y1 ;Do not measure titles for menus - it dies on F12 Return if the ; title is indirected, and is unnecessary in any case. ; J R C 18 March 1993. LDR LR, [handle, #w_taskhandle] CMP LR, #-1 BLNE minwindowx ; R14 = min window width MOVEQ LR, #0 CLRV EQ Pull "PC",VS SUB y1,cx1,cx0 max R14,y1 ; min x-size min R14,x1 ; max x-size ADD cx1,cx0,R14 LDR R14,dx_1 ; R14 <- dx-1 BIC cx1,cx1,R14 ; watch out! ; LDR x1,[handle,#w_wey1] LDR y1,[handle,#w_wey0] SUB x1,x1,y1 BL minwindowy ; R14 = min window height Pull "PC",VS SUB y1,cy1,cy0 max R14,y1 ; min y-size min R14,x1 ; max y-size SUB cy0,cy1,R14 ; adjust lower-right corner LDR R14,dy_1 BIC cy0,cy0,R14 ; watch out! ; ; check that the window is completely on-screen (or within parent's work area) ; LDR R14,[handle,#w_flags] TST R14,#wf_nochecks BNE dontforceit ; Push "x0,y0" ; scroll positions ; Push "cx0,cy0,cx1,cy1" Pull "x0,y0,x1,y1" BL calc_w_x0y0x1y1 SUB cx0,cx0,x0 SUB cy0,cy0,y0 SUB cx1,cx1,x1 SUB cy1,cy1,y1 ; Push "cx0,cy0,cx1,cy1" [ AutoScroll Push "R0" MOV R0,#0 ] [ ChildWindows LDR cx0,newparent ; in: cx0 = parent handle (absolute) BL getparentbounds ; out: cx0,cy0,cx1,cy1 = bounds of parent or screen SUB cx1,cx1,cx0 ; don't assume that cx0,cy0 = 0,0 SUB cy1,cy1,cy0 ] SUB R14,x1,x0 ; never allow window size > screen size CMP R14,cx1 ADDGT x1,x0,cx1 [ AutoScroll ORRGT R0,R0,#wf_icon7:OR:wf_icon6 ; automatically put hscroll on ] SUB R14,y1,y0 ; never allow window size > screen size CMP R14,cy1 SUBGT y0,y1,cy1 ; (keep upper-left corner still) [ AutoScroll ORRGT R0,R0,#wf_icon5:OR:wf_icon6 ; automatically put vscroll on ] [ ChildWindows ADD cx1,cx0,cx1 ; restore cx1,cy1 to top-right corner ADD cy1,cy0,cy1 ] [ Mode22 LDR R14,[handle,#w_origflags] ; if onscreen flags = 0, and AND R14,R14,#wf_iconbits ORR R0,R14,R0 LDR R14,[handle,#w_flags] TST R14,#wf_newformat BICNE R14,R14,#wf_iconbits ORRNE R14,R14,R0 STRNE R14,[handle,#w_flags] Pull "R0" | LDR R14,[handle,#w_flags] [ AutoScroll TST R14,#wf_newformat ORRNE R14,R14,R0 STRNE R14,[handle,#w_flags] Pull "R0" ] ] EOR R14,R14,#ws_open ; if window was closed TST R14,#ws_onscreenonce :OR: ws_open ; or ws_onscreenonce set TSTEQ R14,#wf_onscreen ; or wf_onscreen set BNE %FT01 [ ChildWindows LDR R14,newparent CMP R14,#nullptr ; only use system flags if this is a top-level window BNE %FT01 ] LDRB R14,sysflags TST R14,#sysflags_nobounds ; if cmos bit set, BNE %FT02 ; don't force top-left corner in 01 SUBS R14,x0,cx0 ; first try to keep top-left corner in SUBLT x0,x0,R14 ; by moving the window's position SUBLT x1,x1,R14 SUBS R14,y1,cy1 SUBGT y0,y0,R14 SUBGT y1,y1,R14 02 LDR R14,[handle,#w_flags] ; if onscreen flags = 0, and EOR R14,R14,#ws_open ; if window was closed TST R14,#ws_onscreenonce :OR: ws_open ; or ws_onscreenonce set TSTEQ R14,#wf_onscreen ; or wf_onscreen set [ ChildWindows LDREQ R14,newparent CMPEQ R14,#nullptr ; only use system flags if this is a top-level window ] LDREQB R14,sysflags ANDEQ R14,R14,#sysflags_offscreen TEQEQ R14,#sysflags_offscreen ; if cmos bit set, BEQ %FT01 ; don't force bottom-right corner in SUBS R14,x1,cx1 ;; try to keep bottom-right in SUBGT x0,x0,R14 ;; by moving the window's position SUBGT x1,x1,R14 ;; [ ChildWindows ;; SUBS R14,y0,cy0 ;; use correct lower y bound | ;; SUBS R14,y0,#sz_scrbot ;; sz_scrbot = 0 now (we can overlap the iconbar) ] ;; SUBLT y0,y0,R14 ;; SUBLT y1,y1,R14 ;; 01 LDR R14,[handle,#w_flags] ; if onscreen flags = 0, and EOR R14,R14,#ws_open ; if window was closed TST R14,#ws_onscreenonce :OR: ws_open ; or ws_onscreenonce set TSTEQ R14,#wf_onscreen ; or wf_onscreen set BNE %FT02 [ ChildWindows LDR R14,newparent CMP R14,#nullptr ; only use system flags if this is a top-level window BNE %FT02 ] LDRB R14,sysflags TST R14,#sysflags_nobounds ; if cmos bit set, BNE %FT03 ; don't force top-left corner in 02 SUBS R14,x0,cx0 ; next try to keep the top-left in SUBLT x0,x0,R14 ; by changing the window's size SUBS R14,y1,cy1 SUBGT y1,y1,R14 03 Pull "cx0,cy0,cx1,cy1" ; ADD cx0,cx0,x0 ADD cy0,cy0,y0 ADD cx1,cx1,x1 ADD cy1,cy1,y1 ; Pull "x0,y0" ; scroll positions dontforceit ; check that the window has not been scrunched below the absolute minimum size required for correct redrawing of the borders [ ChildWindows SUB cx1,cx1,cx0 SUB cy0,cy1,cy0 Push "x0,y0" BL minwindow_borders max cx1,x0 max cy0,y0 Pull "x0,y0" ADD cx1,cx0,cx1 SUB cy0,cy1,cy0 ] ; check that scroll bar positions are within limits LDR R14,[handle,#w_wex0] max x0,R14 ; min x scroll point (left) LDR x1,[handle,#w_wex1] SUB R14,cx1,cx0 SUB x1,x1,R14 min x0,x1 ; max x scroll point (right) LDR R14,dx_1 ; R14 <- dx-1 BIC x0,x0,R14 ; LDR R14,[handle,#w_wey1] min y0,R14 ; max y scroll point (top) LDR y1,[handle,#w_wey0] SUB R14,cy1,cy0 ADD y1,y1,R14 max y0,y1 ; min y scroll point (bottom) LDR R14,dy_1 ; R14 <- dy-1 BIC y0,y0,R14 ; ADD R14,userblk,#u_wax0 STMIA R14,{cx0,cy0,cx1,cy1,x0,y0} ; SUB x1,cx1,cx0 ; x1,y1 = new size of window SUB y1,cy1,cy0 ; x0,y0 = new scroll posns ; ; in case we are just scrolling, check whether the outline is changing ; [ :LNOT: ChildWindows ; this lot is done later, when the opens are flushed Push "x0,y0,x1,y1" ; Push "cx0,cy0,cx1,cy1" BL visibleouterportion ; work out area to mark valid at end ADD R14,handle,#w_wax0 LDMIA R14,{cx0,cy0,cx1,cy1} BL subwindowrect MOV R0,#windowrects MOV R1,#invalidrects ; only the currently VALID bits !!! BL subrects Pull "cx0,cy0,cx1,cy1" ; if window was previously open at the same stack position, and we're ONLY scrolling, perform custom invalidation of scrollbars LDR R14,[handle,#w_flags] TST R14,#ws_open LDR R14,[handle,#w_bhandle] LDR R0,[userblk,#u_bhandle] ADDEQ R14,R0,#1 ; ensure no match if window was closed TEQ R0,R14 ADDEQ R14,handle,#w_wax0 ; check old work area coords LDMEQIA R14,{x0,y0,x1,y1} TEQEQ x0,cx0 TEQEQ y0,cy0 TEQEQ x1,cx1 TEQEQ y1,cy1 ; unless all coords are the same [ No32bitCode STR PC,isborderok | MRS R14,CPSR STR R14,isborderok ] MOVNE R0,#windowrects ; we can't mark the border valid BLNE loserects ; invalidate h-scrollbar if we've scrolled horizontally LDR R14,[handle,#w_scx] ; see if h-scroll bar has changed LDR R0,[R13,#0*4] ; get x0 from stack TEQ R14,R0 BEQ %FT01 MOV R0,#7 ; h-scroll bar BL calc_w_iconposn LDR R14,left_width ;<<< LDRB R14,xborder ADD cx0,x0,R14 LDR R14,right_width SUB cx1,x1,R14 LDR R14,dx ADD cx0,cx0,R14 ; border is OK SUB cx1,cx1,R14 LDR R14,dy ADD cy0,y0,R14 SUB cy1,y1,R14 BL subwindowrect ; this bit isn't valid! 01 ; invalidate v-scrollbar if we've scrolled vertically LDR R14,[handle,#w_scy] ; see if v-scroll bar has changed LDR R0,[R13,#1*4] ; get y0 from stack TEQ R14,R0 BEQ %FT01 MOV R0,#5 ; v-scroll bar BL calc_w_iconposn ;<< LDRB R14,yborder LDR R14,down_height ADD cy0,y0,R14 LDR R14,up_height SUB cy1,y1,R14 LDR R14,dy ADD cy0,cy0,R14 ; border is OK SUB cy1,cy1,R14 LDR R14,dx ADD cx0,x0,R14 SUB cx1,x1,R14 BL subwindowrect ; this bit isn't valid! 01 Pull "x0,y0,x1,y1" ; ; transfer the list to 'borderrects' - the list of stationary unchanged rectangles in the border area (work area scrolled) ; LDR R0,rlinks+borderrects LDR R1,rlinks+windowrects STR R0,rlinks+windowrects STR R1,rlinks+borderrects ; swap the lists! ; ; work out offset from old window posn to new (work area coords!) ; also work out whether size or scroll bars are changing - ie. can we block-copy the borders together with the work area ; ADD R14,handle,#w_wax0 LDMIA R14,{R0,R1,cx0,cy0,cx1,cy1} ; SUB R14,cx0,R0 ; R0 = old x0 TEQ R14,x1 SUB R14,cy0,R1 ; cy0 = old y1 TEQEQ R14,y1 TEQEQ cx1,x0 ; cx1 = old scx TEQEQ cy1,y0 ; cy1 = old scy ; LDR x0,[userblk,#u_wax0] ; new x0 LDR y0,[userblk,#u_way1] ; new y1 LDR x1,[userblk,#u_scx] ; new scx LDR y1,[userblk,#u_scy] ; new scy ; SUB cx0,R0,cx1 ; x <- x-scx (old) SUB cy0,cy0,cy1 ; y <- y-scy (old) SUB cx1,x0,x1 ; x <- x-scx (new) SUB cy1,y0,y1 ; y <- y-scy (new) SUB x0,cx1,cx0 ; x-offset SUB y0,cy1,cy0 ; y-offset ; STR x0,xoffset STR y0,yoffset [ No32bitCode STR PC,borderlinked ; save flag status | MRS R14,CPSR STR R14,borderlinked ; save flag status ] ; ; get the old visible portion (with or without scroll bars etc.) ; ADDEQ R14,handle,#w_x0 ADDNE R14,handle,#w_wax0 LDMIA R14,{x0,y0,x1,y1} BL visibleportion_x0y0x1y1 ; get correct amount of window BL int_translatelist ; translate coords ] ; ; close window (we'll reinsert it into the stack later on) ; [ Autoscr BL int_close_window2 ; remove window from stack, and add to openingwinds list | BL int_close_window ; remove window from stack, and add to openingwinds list ] ; ; we need to reopen child windows according to their alignment flags - make a note of how the parent's moving ; [ ChildWindows Push "handle,userblk" ADD R14,handle,#w_ow0 LDMIA R14,{R0-R5} ; R0-R3 = old window work area on screen SUB R4,R0,R4 SUB R5,R3,R5 ; R4,R5 = old work area origin on screen ADD R14,userblk,#u_ow0 LDMIA R14,{R6-R11} ; R6-R9 = new window work area on screen SUB R10,R6,R10 SUB R11,R9,R11 ; R10,R11 = new work area origin on screen SUB R0,R6,R0 SUB R1,R7,R1 SUB R2,R8,R2 SUB R3,R9,R3 SUB R4,R10,R4 SUB R5,R11,R5 Pull "handle,userblk" Push "R0-R5" ; stash for later ] ; ; copy in the new Open_Window data (NB: must be done BEFORE adjusting the children!) ; ADD R6,userblk,#u_ow0 ADD R7,handle,#w_ow0 ; start of Open window params LDMIA R6,{R0-R5} STMIA R7,{R0-R5} ; work area x0,y0,x1,y1,scx,scy ; ; work out outer bounding box from inner ones and flags ; ADD R1,handle,#w_wax0 LDMIA R1,{x0,y0,x1,y1} BL calc_w_x0y0x1y1 ; calculate x0,y0,x1,y1 ADD R1,handle,#w_x0 STMIA R1,{x0,y0,x1,y1} ; ; now deal with moving the children according to the alignment flags ; [ ChildWindows Pull "R0-R5" ; retrieve coordinate offsets LDR R6,newparent ; NB: stash these (corrupted by int_open_window) LDR R7,newalignflags Push "R6,R7,handle,userblk,R12" LDR R12,[handle,#w_children + lh_forwards] 01 LDR R14,[R12,#ll_forwards] CMP R14,#nullptr BEQ %FT02 SUB R12,R12,#w_active_link [ true ; update the toggle-back-to block ADD R14,R12,#w_bwax0 LDMIA R14,{R6-R11} ; R6-R9 = new window work area on screen SUB R10,R6,R10 SUB R11,R9,R11 ; R10,R11 = new work area origin on screen Push "R12,R14" LDR R12,[R12,#w_alignflags] AND R14,R12,#alm_x0 CMP R14,#al0_x0 ; align with: LT => scx, EQ => x0, GT => x1 ADDLT R6,R6,R4 ADDEQ R6,R6,R0 ADDGT R6,R6,R2 AND R14,R12,#alm_y0 CMP R14,#al0_y0 ; align with: LT => scy, EQ => y0, GT => y1 ADDLT R7,R7,R5 ADDEQ R7,R7,R1 ADDGT R7,R7,R3 AND R14,R12,#alm_x1 CMP R14,#al0_x1 ; align with: LT => scx, EQ => x0, GT => x1 ADDLT R8,R8,R4 ADDEQ R8,R8,R0 ADDGT R8,R8,R2 AND R14,R12,#alm_y1 CMP R14,#al0_y1 ; align with: LT => scy, EQ => y0, GT => y1 ADDLT R9,R9,R5 ADDEQ R9,R9,R1 ADDGT R9,R9,R3 AND R14,R12,#alm_scx CMP R14,#al0_scx ; align with: LT => scx, EQ => x0, GT => x1 ADDLT R10,R10,R4 ADDEQ R10,R10,R0 ADDGT R10,R10,R2 AND R14,R12,#alm_scy CMP R14,#al0_scy ; align with: LT => scy, EQ => y0, GT => y1 ADDLT R11,R11,R5 ADDEQ R11,R11,R1 ADDGT R11,R11,R3 SUB R10,R6,R10 SUB R11,R9,R11 ; convert back to scroll offsets Pull "R12,R14" STMIA R14,{R6-R11} ] ADD R14,R12,#w_ow0 LDMIA R14,{R6-R11} ; R6-R9 = new window work area on screen SUB R10,R6,R10 SUB R11,R9,R11 ; R10,R11 = new work area origin on screen Push "R12" LDR R12,[R12,#w_alignflags] AND R14,R12,#alm_x0 CMP R14,#al0_x0 ; align with: LT => scx, EQ => x0, GT => x1 ADDLT R6,R6,R4 ADDEQ R6,R6,R0 ADDGT R6,R6,R2 AND R14,R12,#alm_y0 CMP R14,#al0_y0 ; align with: LT => scy, EQ => y0, GT => y1 ADDLT R7,R7,R5 ADDEQ R7,R7,R1 ADDGT R7,R7,R3 AND R14,R12,#alm_x1 CMP R14,#al0_x1 ; align with: LT => scx, EQ => x0, GT => x1 ADDLT R8,R8,R4 ADDEQ R8,R8,R0 ADDGT R8,R8,R2 AND R14,R12,#alm_y1 CMP R14,#al0_y1 ; align with: LT => scy, EQ => y0, GT => y1 ADDLT R9,R9,R5 ADDEQ R9,R9,R1 ADDGT R9,R9,R3 AND R14,R12,#alm_scx CMP R14,#al0_scx ; align with: LT => scx, EQ => x0, GT => x1 ADDLT R10,R10,R4 ADDEQ R10,R10,R0 ADDGT R10,R10,R2 AND R14,R12,#alm_scy CMP R14,#al0_scy ; align with: LT => scy, EQ => y0, GT => y1 ADDLT R11,R11,R5 ADDEQ R11,R11,R1 ADDGT R11,R11,R3 SUB R10,R6,R10 SUB R11,R9,R11 ; convert back to scroll offsets LDR R12,[SP] ; R12 = child window handle (absolute) Rel R12,R12 Push "R0-R5" MOV R0,R12 ; R0 = relative handle as well Push "R0,R6-R11,R12" ; handle, x0,y0,x1,y1,scx,scy, bhandle LDR R12,[SP,#(8+6+1+4)*4] ; R12 -> workspace (this is important!) MOV userblk,SP BL int_open_window ; NB: shouldn't change stacking order! ADD SP,SP,#8*4 Pull "R0-R5,R12" LDR R12,[R12,#w_active_link + ll_forwards] B %BT01 02 Pull "R0,R1,handle,userblk,R12" STR R0,newparent ; we haven't finished with these yet! STR R1,newalignflags ] ; ; put window into active list (top-level, or as a child of the specified parent) below specified window ; [ ChildWindows LDR R14,newparent CMP R14,#nullptr ADREQL R4,activewinds+lh_forwards-ll_forwards ; top-level window ADDNE R4,R14,#w_children+lh_forwards-ll_forwards ; child window - NB: parent already checked | ; R4 points at activewinds header as if it were a link for inserting forwards of ADRL R4,activewinds+lh_forwards-ll_forwards ] ; ; Deal with layering and special bhandles ; [ ForegroundWindows :LAND: ChildWindows Push "R4" Push "x0, x1, handle" ; Determine type of opening window LDR R14, [handle, #w_flags] TST R14, #wf_backwindow MOVNE x0, #2 MOVEQ x0, #1 TST r14, #wf_inborder MOVNE x0, #0 ; Determine type of window-to-open-behind LDR handle, [userblk, #u_bhandle] CMP handle, #nullptr ; -1 MOVEQ x1, #3 BEQ %FT01 CMP handle, #nullptr2 ; -2 MOVEQ x1, #4 BEQ %FT01 CMP handle, #-3 MOVEQ x1, #5 BEQ %FT01 BL checkhandle ; handle must be open, and have the same parent LDRVC R14, [handle, #w_flags] TST R14, #wf_backwindow MOVNE x1, #2 MOVEQ x1, #1 TST R14, #wf_inborder MOVNE x1, #0 TST R14, #ws_open SETV EQ [ ChildWindows LDRVC R14, [handle, #w_parent] LDRVC R0, newparent TEQVC R0, R14 SETV NE ] ADDVC R4, handle, #w_active_link MOVVS x1, #4 CLRV 01 CMP x1, #3 BHS %FT02 CMP x0, #1 TEQHS x1, #0 BEQ %FT02 CMP x1, #1 TEQHS x0, #0 Pull "x0, x1, handle", NE ADDNE sp, sp, #4 ; use the R4 calculated from u_bhandle BNE openwlp3end 02 ADD x0, x0, x1, LSL#2 ; look up which method to determine where to open window ADR R0, openwlp3_lookuptable LDRB x0, [R0, x0] ADR R0, openwlp3_jumptable ADD R0, R0, x0, LSL#2 Pull "x0, x1, handle" Pull "R4" ; use top-of-stack R4 ADR R14, openwlp3end ; where to return control to MOV PC, R0 openwlp3_lookuptable ; fg std bg DCB 0, 1, 1, 0 ; opened behind a fg window DCB 1, 0, 0, 0 ; opened behind a std window DCB 3, 0, 0, 0 ; opened behind a bg window DCB 0, 1, 1, 0 ; opened behind -1 DCB 1, 2, 2, 0 ; opened behind -2 (or invalid handle not in range -1 - -3) DCB 3, 3, 3, 0 ; opened behind -3 ; backwindows behaviour is preserved for compatibility reasons openwlp3_jumptable B openwlp3end ; method 0 - already set up B openwlp3_skip_foreground ; method 1 B openwlp3_skip_standard ; method 2 B openwlp3_skip_to_bottom ; method 3 openwlp3_skip_to_bottom Push "R14" ; ; R0->next window down stack, R14=its forwards pointer which is also lh_indicator for list headers ; 01 LDR R0,[R4,#ll_forwards] LDR R14,[R0,#ll_forwards] ; ; Hit bottom of stack (next window is list header) ; CMP R14,#nullptr Pull "PC", EQ ; ; Move down below to next window ; MOV R4,R0 B %BT01 openwlp3_skip_standard Push "R14" BL openwlp3_skip_foreground ; ; R0->next window down stack, R14=its forwards pointer which is also lh_indicator for list headers ; 01 LDR R0,[R4,#ll_forwards] LDR R14,[R0,#ll_forwards] ; ; Hit bottom of stack (next window is list header) ; CMP R14,#nullptr Pull "PC", EQ ; ; Is next window a background window? ; LDR R14,[R0,#w_flags-w_active_link] TST R14,#wf_backwindow Pull "PC", NE ; ; Next window is still a normal window, move down below to that ; MOV R4,R0 B %BT01 openwlp3_skip_foreground Push "R14" ; ; R0->next window down stack, R14=its forwards pointer which is also lh_indicator for list headers ; 01 LDR R0,[R4,#ll_forwards] LDR R14,[R0,#ll_forwards] ; ; Hit bottom of stack (next window is list header) ; CMP R14,#nullptr Pull "PC", EQ ; ; Is next window a non-foreground window? ; LDR R14,[R0,#w_flags-w_active_link] TST R14,#wf_inborder Pull "PC", EQ ; ; Next window is still a foreground window, move down below to that ; MOV R4,R0 B %BT01 | ; :LNOT: ForegroundWindows ; Check handle for being 'On top' Push "handle" LDR handle,[userblk,#u_bhandle] CMP handle,#nullptr Pull "handle",EQ BEQ openwlp3end ; Check for special cases explicitly, rather than generating an error and then swallowing it [ ChildWindows CMP handle,#nullptr2 ; open at back (but in front of backwindow) CMPNE handle,#-3 ; open behind backwindow Pull "handle",EQ BEQ openwlp3 ] ; Check bhandle for being a valid window - must be open, and have the same parent! ; CLRV ; NK 348 BL checkhandle LDRVC R14,[handle,#w_flags] TST R14,#ws_open SETV EQ [ ChildWindows LDRVC R14,[handle,#w_parent] ; check that bhandle has the same parent LDRVC R0,newparent TEQVC R0,R14 SETV NE ] ADDVC R4,handle,#w_active_link Pull "handle" BVC openwlp3end ; Handle isn't a valid window, drop to the bottom openwlp3 ; R0->next window down stack, R14=its forwards pointer which is also lh_indicator for list headers LDR R0,[R4,#ll_forwards] LDR R14,[R0,#ll_forwards] ; ; Hit bottom of stack (next window is list header) ; CMP R14,#nullptr BEQ openwlp3end ; ; Is next window a back window? ; LDR R14,[R0,#w_flags-w_active_link] TST R14,#wf_backwindow LDRNE R14,[userblk,#u_bhandle] CMPNE R14,#-3 ; Do we want to hide this window ? BNE openwlp3end ; ; Next window isn't a back window, move down below to that ; MOV R4,R0 B openwlp3 ] ; end ForegroundWindows openwlp3end ; R4 -> window link to insert our window forwards of. ; On the active stack forwards listwise means behind windowstackwise LDR R14,[R4,#ll_forwards] STR R4,[handle,#w_active_link+ll_backwards] STR R14,[handle,#w_active_link+ll_forwards] ADD R0,handle,#w_active_link Debug child,"Insert window into back/forwards",R0,R4,R14 STR R0,[R4,#ll_forwards] STR R0,[R14,#ll_backwards] [ ChildWindows LDR R14,newparent STR R14,[handle,#w_parent] ; this is now the absolute handle of the parent LDR R14,newalignflags STR R14,[handle,#w_alignflags] ] LDR R14,[handle,#w_flags] ORR R14,R14,#ws_open STR R14,[handle,#w_flags] BL calc_w_status ; set up flags ; ; now done later (when the opens are flushed) ; get visible portion of new window (with or without scroll bars) ; [ :LNOT: ChildWindows LDR R14,borderlinked [ No32bitCode TEQP R14,#0 ; restore status | MSR CPSR_f,R14 ] ADDEQ R14,handle,#w_x0 ADDNE R14,handle,#w_wax0 LDMIA R14,{x0,y0,x1,y1} BL visibleportion_x0y0x1y1 ; new visible list (-ish) ; ; clip old visible region to the new one, and mark new list invalid ; MOV R0,#oldwindowrects MOV R1,#windowrects BL intrects ; BL visibleouterportion BL markinvalidrects BL losewindowrects ; ; use snazzy new method to block-copy the old list ; BL int_blockcopy ; LDR R14,borderlinked [ No32bitCode TEQP R14,#0 ; exit if border linked | MSR CPSR_f,R14 ] BEQ openfinished ; ; border unlinked, but in same place (ie. scrolling) ; mark borders valid, except for the relevant scroll bar(s) ; LDR R14,isborderok ; always redraw border if it toggled [ No32bitCode TEQP R14,#0 ; set flags | MSR CPSR_f,R14 ] ; MOVEQ R0,#invalidrects ; mark border bits valid again MOVEQ R1,#borderrects BLEQ subrects ; openfinished MOV R0,#borderrects BL loserects ] ; ; work out whether the window is now toggled, and redraw if necessary ; BL calctoggle ; invalidates icon (OLD position) if necessary LDR R14,[handle,#w_flags] BIC R14,R14,#ws_onscreenonce ; only cancel this on Open_Window STR R14,[handle,#w_flags] ; (not on Set_Extent) ; [ PoppingIconBar :LAND: :LNOT: OldStyleIconBar LDR R14, iconbar_pop_state ; don't bother if already at back TEQ R14, #pop_Front TEQNE R14, #pop_HeldByMenu TEQNE R14, #pop_Front2 LDREQ R14, [handle, #w_bhandle] CMPEQ R14, #-1 ; don't bother if not coming to front LDREQ R14, [handle, #w_parent] CMPEQ R14, #-1 ; don't bother if a child window LDREQ R14, [handle, #w_flags] TSTEQ R14, #wf_inborder ; don't bother for screensavers, interactive help etc. BNE %FT02 LDR userblk, menuSP CMP userblk, #0 BLT %FT01 ADR R14, menuhandles LDR R14, [userblk, R14] Abs R14, R14 TEQ handle, R14 ; don't bother if topmost existing menu BEQ %FT02 01 LDR R14, menuhandle ; menuhandles and menuSP are not necessarily set up yet Abs R14, R14 TEQ handle, R14 ; don't bother if the deepest menu or dialogue box (may be new) LDRNE R14, iconbarhandle Abs R14, R14, NE TEQNE handle, R14 ; just in case the icon bar is the only window BEQ %FT02 Push "handle" MOV handle, R14 LDR R14, [handle, #w_flags] ORR R14, R14, #wf_backwindow STR R14, [handle, #w_flags] ADD R14, handle, #w_wax0 LDMIA R14, {R0-R5} [ HideIconBar MOV R6, #-3 | MOV R6, #-2 ] Push "R0-R6" ; build block on stack LDR R14, iconbarhandle Push "R14" ; window handle MOV userblk, sp BL int_open_window ADD sp, sp, #8*4 MOVVC R14, #pop_Back STRVC R14, iconbar_pop_state Pull "handle" 02 ] ; Pull "LR" ; drop through Debug opn,"Opening window complete" CheckAllWindows "int_open_window (after)" ; ; When the window extent changes, and dragtype = drag_size, ; recalculate the dragging variables (ie. parent box size) ; NB: also called from Open_Window (see above) ; recalcdrag Push "LR" ; Rel R14,handle LDR R0,draghandle TEQ R0,R14 LDREQ R0,dragtype TEQEQ R0,#drag_size BLEQ int_drag_box_continue ; Pull "PC" ; ; Entry: handle -> window definition ; Exit: [handle,#w_flags] updated so ws_toggled => full size or not ; toggle icon will be redrawn if state has changed ; calctoggle Push "R1,cx0-y1,LR" ; LDR R1,[handle,#w_flags] ; remember old setting ; ADD R14,handle,#w_wax0 LDMIA R14,{x0,y0,x1,y1} SUB cx0,x1,x0 SUB cy0,y1,y0 ; cx0,cy0 = current work area size ADD R14,handle,#w_wex0 LDMIA R14,{x0,y0,x1,y1} SUB cx1,x1,x0 SUB cy1,y1,y0 ; cx1,cy1 = max work area size ; ADD R14,handle,#w_x0 LDMIA R14,{x0,y0,x1,y1} SUB x0,x1,x0 SUB y0,y1,y0 ; x0,y0 = window outline size [ ChildWindows Push "cx0,cy0,cx1,cy1" LDR cx0,[handle,#w_parent] BL getparentbounds ; new feature: if nochecks set, we still only toggle to full screen size SUB x1,cx1,cx0 SUB y1,cy1,cy0 Pull "cx0,cy0,cx1,cy1" | TST R1,#wf_nochecks ; screen limit doesn't apply here MOVNE x1,#bignum LDREQ x1,scrx1 LDR y1,scry1 ; x1,y1 = max window outline size ] ; [ togglebits CMP cx0,cx1 ; is it as wide as it can be? CMPLT x0,x1 BICLT R14,R1,#ws_toggled :OR: ws_toggling :OR: ws_toggled2 BLT %FT02 ; no ; TST R1,#ws_toggled2 ; is the extra toggling bit set? BEQ %FT10 ; LDR R14,[handle,#w_toggleheight] TEQ R14,cy0 ; height is correct, we're still shift-toggled BICEQ R14,R1,#ws_toggled :OR: ws_toggling ; ORREQ R14,R14,#ws_toggled2 BEQ %FT02 10 CMP cy0,cy1 ; is it as tall as it can be? CMPLT y0,y1 BIC R14,R1,#ws_toggled :OR: ws_toggling :OR: ws_toggled2 ORRGE R14,R14,#ws_toggled 02 Debug opn,"calctoggle sets flags for handle, from, to",handle,R1,R14 STR R14,[handle,#w_flags] ; EOR R14,R14,R1 TST R14,#ws_toggled :OR: ws_toggled2 ; has either toggle bit changed? Pull "R1,cx0-y1,PC",EQ | CMP cx0,cx1 ; if up to max extent, CMPLT x0,x1 ; or up to max screen size BLT %FT01 ; CMP cy0,cy1 ; and y-coord is the same, CMPLT y0,y1 01 BIC R14,R1,#ws_toggled :OR: ws_toggling ORRGE R14,R14,#ws_toggled 02 Debug opn,"calctoggle sets flags for handle, from, to",handle,R1,R14 STR R14,[handle,#w_flags] ; EOR R14,R14,R1 TST R14,#ws_toggled ; has the toggle bit changed? Pull "R1,cx0-y1,PC",EQ ] ; To redraw the toggle icon, we must rely on the snazzy new int_flush_open code to spot that the 'toggled' bit has been altered MOV R0,#4 ; toggle icon [ ChildWindows BL int_force_redraw_border ; force a redraw of the toggle icon | BL calc_w_iconposn BLVC visibleportion_x0y0x1y1 BLVC markinvalidrects ; ensure it's redrawn ] Pull "R1,cx0-y1,PC" ;;----------------------------------------------------------------------------- ;; int_flush_opens ;; In various windows are marked as having been moved ;; their old and new positions differ ;; [oldinvalidrects] indicates what was valid before the opens ;; [oldactivewinds] indicates the old stacking order ;; [handle,#w_old_data] indicates the old positions of the windows ;; [handle,#w_new_data] indicates the current positions of the windows ;; note that w_old_flags indicates whether the window was open ;; w_new_flags indicates whether the window is open ;; Out old and new positions brought into line ;; [invalidrects] updated to reflect bits that need redrawing ;; various rectangles may have been block-copied ;;----------------------------------------------------------------------------- [ ChildWindows int_flush_opens ROUT CheckAllWindows "int_flush_opens (before)" Push "handle,userblk,LR" LDRB R14,openspending TEQ R14,#0 Pull "handle,userblk,PC",EQ Push "R0-y1" ; save all registers! MOV R14,#0 STRB R14,openspending Debug opn,"int_flush_opens" [ Autoscr ; Remember the drag window's old visible area (only used for clipped dragboxes) ; This is necessary because data in window block has been forgotten when we get round to blockcopying ; Also use this opportunity to check, for window-anchored rubber-box drags, whether the work area has moved Push "R0, x0, y0, x1, y1" LDR R14, dragflags TST R14, #dragf_anchor :OR: dragf_clip LDRNE R14, dragtype TEQNE R14, #0 MOVEQ R0, #0 ; don't bother doing either if not doing a window-related drag LDRNE R0, draghandle Abs R0, R0, NE ADDNE R0, R0, #w_old_wax0 LDMNEIA R0, {x0, y0, x1, y1} ASSERT :INDEX:tempworkspace = 0 STMNEIA wsptr, {x0, y0, x1, y1} ; store old visible area in tempworkspace +0 - +12 ADDNE R0, R0, #w_opening_link - w_old_wax0 ; make suitable for comparison with opening window links LDR x0, dragflags TST x0, #dragf_anchor MOVEQ R0, #0 ; only link to work area if the correct flag bit is set LDR x0, dragtype TEQ x0, #drag_user2 TEQNE x0, #drag_subr_size TEQNE x0, #drag_subr_size2 MOVNE R0, #0 ; don't link to work area unless drag type 6, 9 or 11 MOV x0, #0 ; flag that we haven't found it yet Debug autoscr, "About to scan opening handles in int_flush_opens" ] ; child windows can be ignored if they are moving with their parent's work area ; for each window in the 'opening' list, go through its list of children (from back to front) ; removing them from the list if they're moving with the parent (and not changing stack order) LDR handle,openingwinds+lh_forwards 10 [ Autoscr TEQ handle, R0 MOVEQ x0, #1 ; yes, the drag's window is in the opening list ] LDR R14,[handle,#ll_forwards] CMP R14,#nullptr MOVNE R14,#0 STRNE R14,[handle,#w_xoffset - w_opening_link] LDRNE handle,[handle,#ll_forwards] BNE %BT10 [ Autoscr TEQ x0, #1 ; was the drag's window in the opening list? BNE %FT06 Debug autoscr, "Before adjust:", x0, y0, x1, y1 LDR R14, dragflags TST R14, #dragf_clip BLEQ defaultwindow BLEQ forcedrag_off ; remove old dragbox now - but only if not clipped ADR R14, dragx0 LDMIA R14, {x0, y0, x1, y1} ; load old drag box position LDR handle, draghandle Abs handle, handle LDR R0, [handle, #w_wax0] LDR R14, [handle, #w_scx] SUB R0, R0, R14 LDR R14, [handle, #w_old_wax0] SUB R0, R0, R14 LDR R14, [handle, #w_old_scx] ADD R0, R0, R14 ; R0 now holds the horizontal shift of the work area ADD x0, x0, R0 LDR R0, [handle, #w_way1] LDR R14, [handle, #w_scy] SUB R0, R0, R14 LDR R14, [handle, #w_old_way1] SUB R0, R0, R14 LDR R14, [handle, #w_old_scy] ADD R0, R0, R14 ; R0 now holds the vertical shift of the work area ADD y1, y1, R0 LDR R0, dragflags TST R0, #dragf_clip ASSERT :INDEX:tempworkspace = 0 ADDNE R14, wsptr, #4*4 ; remember position to plot new dragbox at ADREQ R14, dragx0 ; store updated position back again STMIA R14, {x0, y0, x1, y1} BLEQ forcedrag_on ; plot new dragbox now (corrupts flags) - but only if not clipped LDRB R14, dragflag TST R0, #dragf_clip TEQNE R14, #0 MOVNE R14, #2 ; special dragflag code to indicate redraw position is in tempworkspace STRNEB R14, dragflag Debug autoscr, "After adjust:", x0, y0, x1, y1 06 Pull "R0, x0, y0, x1, y1" ] ; having marked all windows on the list as 'unvisited', we can scan the list LDR handle,openingwinds+lh_forwards 11 ASSERT ll_forwards = 0 LDR R14,[handle],#-w_opening_link CMP R14,#nullptr BEQ %FT12 BL remove_children ; attempt to remove child windows from the list (transfer to heldover list) LDR handle,[handle,#w_opening_link + ll_forwards] B %BT11 12 ; invalidate relevant border area of parent if child window with wf_inborder set is moving (non-optimized) ; currently only the h-scrollbar moves to accommodate overlapping child windows LDR handle,openingwinds+lh_forwards 13 ASSERT ll_forwards = 0 LDR R14,[handle],#-w_opening_link CMP R14,#nullptr BEQ %FT19 MOV userblk,#w_old_data BL check_scrollbar_overlap ; note that old and new parents might be different MOV userblk,#w_new_data ; so we have to check these twice BL check_scrollbar_overlap ; (up to 4 parent scrollbars may be invalidated) LDR handle,[handle,#w_opening_link + ll_forwards] B %BT13 19 ; copy the invalid rectangle list first, ; so int_flush_open can distinguish between stuff that's already invalid, and stuff that's being made invalid MOV R0,#invalidrects MOV R1,#oldinvalidrects BL copyrects ; copy invalid rectangle list ; call int_flush_open for each window remaining in the opening list LDR handle,openingwinds+lh_forwards 01 ; [ debugopn ; Push "R0-R12, R14" ; MOV R0, #invalidrects ; BL listrects ; MOV R0, #oldinvalidrects ; BL listrects ; Pull "R0-R12, R14" ; ] LDR R14,[handle,#ll_forwards] CMP R14,#nullptr BEQ %FT02 ASSERT ll_forwards = 0 LDR R14,[handle],#-w_opening_link BL int_flush_open ; does NOT remove this window from the list LDR handle,[handle,#w_opening_link + ll_forwards] B %BT01 ; invalidrects has now been updated, so we can lose the old set 02 MOV R0,#oldinvalidrects BL loserects ; go through the list of 'heldover' windows, updating their information LDR handle,heldoverwinds B %FT29 27 ASSERT (w_old_end - w_old_parent ) = 13*4 ASSERT handle = R10 ; Debug opn, "Copying new data to old for held-over handle", handle ADD R14,handle,#w_parent ; copy from new data to old ADD R9, handle,#w_old_parent LDMIA R14!,{R0-R6} STMIA R9!, {R0-R6} ; copy first 7 words LDMIA R14!,{R0-R5} STMIA R9!, {R0-R5} ; then the next 6 words LDR handle,[handle,#w_opening_link + ll_backwards] 29 CMP handle,#nullptr BNE %BT27 STR handle,heldoverwinds ; go through the list of 'opening' windows, updating their information ; TODO: discard windows that couldn't be deleted straightaway LDR handle,openingwinds + lh_forwards 03 LDR R14,[handle, #ll_forwards] ; BJGA: *not* #w_opening_link + ll_forwards !! CMP R14,#nullptr BEQ %FT04 ASSERT (w_old_end - w_old_parent ) = 13*4 ASSERT handle = R10 ; [ debugopn ; SUB handle, handle, #w_opening_link ; Debug opn, "Copying new data to old for opening handle", handle ; ADD handle, handle, #w_opening_link ; ] ADD R14,handle,#w_parent - w_opening_link ; copy from new data to old ADD R9, handle,#w_old_parent - w_opening_link LDMIA R14!,{R0-R6} STMIA R9!, {R0-R6} ; copy first 7 words LDMIA R14!,{R0-R5} STMIA R9!, {R0-R5} ; then the next 6 words LDR handle,[handle,#ll_forwards] B %BT03 ; correct the stack separately, as it requires more complex treatment 04 ; Debug opn,"**** copy_new_links_to_old for activewinds" ADRL R0,activewinds [ true ; was STB ADRL R1,oldactivewinds | ADR R1,oldactivewinds ] BL copy_new_links_to_old ; correct child window stacks (use allwinds for this, since children can be moved while the parent is closed) LDR handle,allwinds + lh_forwards 05 LDR R14,[handle,#ll_forwards] CMP R14,#nullptr BEQ %FT06 ; Debug opn,"**** copy_new_links_to_old for children of",handle ADD R0,handle,#w_children - w_all_link ADD R1,handle,#w_old_children - w_all_link BL copy_new_links_to_old LDR handle,[handle,#ll_forwards] B %BT05 06 ; now perform the block-copy of all relevant rectangles BL int_blockcopy_all ; frees rectangles as it copies them, and removes windows from the 'opening' list Debug opn,"int_flush_opens exitting" CheckAllWindows "int_flush_opens (after)" [ Autoscr LDRB R14, dragflag ; Now that we've called int_blockcopy_all, the dragbox has been correctly TEQ R14, #2 ; repositioned within all the copied rectangles (provided any change was, in MOVEQ R14, #1 ; fact, necessary due to anchoring, of course), so we can go back to STREQB R14, dragflag ; forcedrag_on getting its coordinates from dragx0 - dragy1. Push "x0, y0, x1, y1", EQ ASSERT :INDEX:tempworkspace = 0 ADDEQ R14, wsptr, #4*4 LDMEQIA R14, {x0, y0, x1, y1} ADREQ R14, dragx0 STMEQIA R14, {x0, y0, x1, y1} Pull "x0, y0, x1, y1", EQ ] [ debugcheck :LAND: debug LDR handle,allwinds + lh_forwards 10 ASSERT ll_forwards = 0 LDR R14,[handle],#-w_all_link CMP R14,#nullptr BEQ %FT20 LDR R14,[handle,#w_opening_link+ll_forwards] TEQ R14,#0 BEQ %FT15 Debug check,"**** After int_flush_opens, window still has non-null w_opening_link ****",handle MOV R14,#0 STR R14,[R14] 15 ADD R14,handle,#w_old_wax0 LDMIA R14,{cx0,cy0,cx1,cy1} ADD R14,handle,#w_wax0 LDMIA R14,{x0,y0,x1,y1} TEQ cx0,x0 TEQEQ cy0,y0 TEQEQ cx1,x1 TEQEQ cy1,y1 ADDEQ R14,handle,#w_old_x0 LDMEQIA R14,{cx0,cy0,cx1,cy1} ADDEQ R14,handle,#w_x0 LDMEQIA R14,{x0,y0,x1,y1} TEQEQ cx0,x0 TEQEQ cy0,y0 TEQEQ cx1,x1 TEQEQ cy1,y1 LDREQ cx0,[handle,#w_old_scx] LDREQ cy0,[handle,#w_old_scy] LDREQ x0,[handle,#w_scx] LDREQ y0,[handle,#w_scy] TEQEQ cx0,x0 TEQEQ cy0,y0 LDREQ cx0,[handle,#w_old_flags] LDREQ x0,[handle,#w_flags] EOREQ cx0,cx0,x0 TSTEQ cx0,#ws_open BEQ %FT17 Debug check,"**** After int_flush_opens, old window data disagrees",handle ADD R14,handle,#w_old_wax0 LDMIA R14,{cx0,cy0,cx1,cy1} Debug check,"old work area",cx0,cy0,cx1,cy1 ADD R14,handle,#w_wax0 LDMIA R14,{cx0,cy0,cx1,cy1} Debug check,"new work area",cx0,cy0,cx1,cy1 ADD R14,handle,#w_old_x0 LDMIA R14,{cx0,cy0,cx1,cy1} Debug check,"old outline",cx0,cy0,cx1,cy1 ADD R14,handle,#w_x0 LDMIA R14,{cx0,cy0,cx1,cy1} Debug check,"new outline",cx0,cy0,cx1,cy1 LDR cx0,[handle,#w_old_scx] LDR cy0,[handle,#w_old_scy] LDR R14,[handle,#w_old_flags] Debug check,"old scx,scy,flags",cx0,cy0,R14 LDR cx0,[handle,#w_scx] LDR cy0,[handle,#w_scy] LDR R14,[handle,#w_flags] Debug check,"new scx,scy,flags",cx0,cy0,R14 MOV R14,#0 STR R14,[R14] 17 LDR handle,[handle,#w_all_link+ll_forwards] B %BT10 20 ] Pull "R0-y1,handle,userblk,PC" LTORG ;.............................................................................. ; In handle -> child window to consider ; userblk = offset to old/new data (ie. w_old_data or w_new_data) ; Out old h/v scrollbar(s) of parent invalidated if child has/had wf_inborder set and overlaps/ped parent's scrollbars check_scrollbar_overlap Entry "handle" ADD R0,handle,userblk ; R0 -> child window's data (old or new) LDR R14,[R0,#w_flags - w_new_data] TST R14,#ws_open TSTNE R14,#wf_inborder LDRNE R1,[R0,#w_parent - w_new_data] CMPNE R1,#nullptr EXIT EQ ADD userblk,R1,userblk ; userblk -> parent window's data (old or new) ; Debug ,"check_scrollbar_overlap (h): handle,R1, R0,userblk",handle,R1,R0,userblk ; check whether h-scrollbar of parent should be invalidated (only if it's not changing anyway) LDR R2,=ws_open :OR: wf_icon7 LDR R14,[R1,#w_old_flags] AND R14,R14,R2 TEQ R14,R2 LDREQ R14,[R1,#w_flags] ANDEQ R14,R14,R2 TEQEQ R14,R2 BNE %FT18 ; work out whether the child window overlaps the parent's h-scrollbar LDR y1,dy LDR cy0,[R0,#w_y0 - w_new_data] LDR y0,[userblk,#w_y0 - w_new_data] ADD y0,y0,y1 CMP cy0,y0 BGT %FT18 ; invalidate OLD h-scrollbar of the parent (must have been present if we got this far) 17 LDR x0,[R1,#w_old_x0] LDR y0,[R1,#w_old_y0] LDR x1,[R1,#w_old_wax1] LDR y1,[R1,#w_old_way0] LDR R14,[R1,#w_old_flags] AND R14,R14,#wf_icon5 :OR: wf_icon6 TEQ R14,#wf_icon6 LDREQ R14,vscroll_width SUBEQ x1,x1,R14 ; Debug ,"invalidating old h-scrollbar of parent",x0,y0,x1,y1 Push "R0,R1,handle,userblk" MOV handle,R1 BL oldvisibleportion_x0y0x1y1 ; windowrects = old visible portion of parent's h-scrollbar MOV R1,#wf_inborder BL oldsubtract_children ; don't redraw the child windows that can overlap the parent's borders ; BL markoldinvalidrects ; add to OLD invalid list - old scrollbar is not to be trusted BL markinvalidrects ; in fact we need to add to both lists (oldinvalidrects is supposed to be a copy) BL losewindowrects Pull "R0,R1,handle,userblk" 18 ; check whether v-scrollbar of parent should be invalidated (only if it's not changing anyway) ; Debug ,"check_scrollbar_overlap (v): handle,R1, R0,userblk",handle,R1,R0,userblk LDR R2,=ws_open :OR: wf_icon5 LDR R14,[R1,#w_old_flags] AND R14,R14,R2 TEQ R14,R2 LDREQ R14,[R1,#w_flags] ANDEQ R14,R14,R2 TEQEQ R14,R2 EXIT NE ; work out whether the child window overlaps the parent's v-scrollbar LDR x0,dx LDR cx1,[R0,#w_x1 - w_new_data] LDR x1,[userblk,#w_x1 - w_new_data] SUB x1,x1,x0 CMP cx1,x1 EXIT LT ; invalidate OLD v-scrollbar of the parent (must have been present if we got this far) 27 LDR x0,[R1,#w_old_wax1] LDR y0,[R1,#w_old_way0] LDR x1,[R1,#w_old_x1] LDR y1,[R1,#w_old_way1] LDR R14,[R1,#w_old_flags] AND R14,R14,#wf_icon6 :OR: wf_icon7 TEQ R14,#wf_icon6 LDREQ R14,hscroll_height ADDEQ y0,y0,R14 ; Debug ,"invalidating old v-scrollbar of parent",x0,y0,x1,y1 MOV handle,R1 BL oldvisibleportion_x0y0x1y1 ; windowrects = old visible portion of parent's h-scrollbar MOV R1,#wf_inborder BL oldsubtract_children ; don't redraw the child windows that can overlap the parent's borders ; BL markoldinvalidrects ; add to OLD invalid list - old scrollbar is not to be trusted BL markinvalidrects ; in fact we need to add to both lists (oldinvalidrects is supposed to be a copy) BL losewindowrects EXIT LTORG ;.............................................................................. ; Debugging routine to detect corruption of windows as it happens ; Use the CheckAllWindows macro to invoke this code ; Out EQ => one or more windows were found to be corrupt ; NE => all windows OK ; ; Currently this is used to check the window flags only [ debugcheck :LAND: debug checkallwindows ROUT Push "R0-R11,LR" LDR handle,allwinds + lh_forwards LDR R0,=&FFFF 01 LDR R14,[handle,#ll_forwards] CMP R14,#nullptr BEQ %FT02 LDR R14,[handle,#w_flags - w_all_link] AND R14,R14,R0 TEQ R14,R0 Pull "R0-R11,PC",EQ ; EQ => window flags are naff! LDR handle,[handle,#ll_forwards] B %BT01 02 CMP PC,#0 ; NE => window flags all OK Pull "R0-R11,PC" LTORG ] ;.............................................................................. ; Optimization to treat child windows that move with the parent as part of the parent's background ; In handle -> parent window (on the 'opening' list) ; Out child windows moved onto the heldover list if they're moving with the parent window anyway ; cx0-cy1,x0-y1 corrupted ; All children of parents that are on the opening list will also be on the list, so we can just scan that remove_children ROUT Push "R0,R1,LR" LDR R14,[handle,#w_xoffset] ; 0 => not yet scanned TEQ R14,#0 Pull "R0,R1,PC",NE ; we've scanned this one MOV R14,#1 STR R14,[handle,#w_xoffset] ; mark as 'done' Debug child,"remove_children from opening list for window",handle BL isborderlinked ; out: borderlinked EQ => border will be block-copied with work area LDR cx1,[handle,#w_old_wax0] LDR R14,[handle,#w_old_scx] SUB cx1,cx1,R14 ; cx1 = parent's old work area origin x LDR cy1,[handle,#w_old_way1] LDR R14,[handle,#w_old_scy] SUB cy1,cy1,R14 ; cy1 = parent's old work area origin y LDR x1,[handle,#w_wax0] LDR R14,[handle,#w_scx] SUB x1,x1,R14 ; x1 = parent's new work area origin x LDR y1,[handle,#w_way1] LDR R14,[handle,#w_scy] SUB y1,y1,R14 ; y1 = parent's new work area origin y SUB x1,x1,cx1 SUB y1,y1,cy1 ; x1,y1 = change in parent's work area origin LDR R0,[handle,#w_old_children + lh_backwards] LDR R1,[handle,#w_children + lh_backwards] 01 LDR R14,[R0,#ll_backwards] CMP R14,#nullptr BEQ %FT20 ADD R14,R0,#w_active_link - w_old_link CMP R14,R1 BNE %FT20 ; give up if old and new stacks disagree [ debug LDR R14,[R1,#w_opening_link + ll_forwards - w_active_link] CMP R14,#0 STREQ R14,[R14] ; all children must be on the list if the parent hasn't been scanned yet! ] LDR R14,[R1,#w_flags - w_active_link] LDR R2,[R1,#w_old_flags - w_active_link] EOR R2,R2,R14 LDR R14,=ws_hasfocus :OR: wf_inborder :OR: wf_iconbits TST R2,R14 ; can't optimise if any of these bits are changing BNE %FT20 TST R14,#wf_inborder ; if child overlaps the border, LDRNE R14,borderlinked ; we can only optimize it if the parent isn't resizing or scrolling [ No32bitCode TEQNEP R14,#0 BNE %FT20 | MSRNE CPSR_f,R14 BNE %FT20 ] Push "x1,y1" ADD R14,R1,#w_old_wax0 - w_active_link LDMIA R14,{cx0,cy0,cx1,cy1,x0,y0} SUB cx1,cx1,cx0 SUB cy1,cy1,cy0 ASSERT w_scx = w_wax0 + 4*4 ADD R14,R1,#w_scx - w_active_link LDMIA R14,{x1,y1} ; if child scrolls, we must deal with it separately CMP x0,x1 CMPEQ y0,y1 Debug child,"--- old/new scroll",x0,y0,x1,y1 LDMEQDB R14,{x0,y0,x1,y1} ; get new work area coordinates SUBEQ x1,x1,x0 SUBEQ y1,y1,y0 CMPEQ cx1,x1 ; make sure size hasn't changed either CMPEQ cy1,y1 Debug child,"--- old/new size",cx1,cy1,x1,y1 Pull "x1,y1" SUBEQ x0,x0,cx0 SUBEQ y0,y0,cy0 ; x0,y0 = change in child window's coordinates Debug child,"--- child/parent offset",x0,y0,x1,y1 CMPEQ x0,x1 CMPEQ y0,y1 BNE %FT20 ; NB: don't scan any more once we find one that can't be removed (might overlap) ; we must transfer the window onto a different list, so its info will be updated later on Debug child,"*** Child moving with parent",R1,handle ADD R14,R1,#w_opening_link - w_active_link LDMIA R14,{x0,y0} STR x0,[y0,#ll_forwards] STR y0,[x0,#ll_backwards] MOV R14,#0 ; mark as not being in the chain STR R14,[R1,#w_opening_link + ll_forwards - w_active_link] LDR R14,heldoverwinds STR R14,[R1,#w_opening_link + ll_backwards - w_active_link] ; sneaky - re-use this for the singly-linked list SUB R14,R1,#w_active_link STR R14,heldoverwinds ; OK, we've removed this window, but if any of its children can't be removed, we must stop removing siblings of this window Push "handle" SUB handle,R0,#w_old_link BL remove_children LDR R14,[handle,#w_yoffset] Pull "handle" CMP R14,#nullptr BNE %FT20 ; OK, we'll have to give up now - our siblings and the parent's etc. won't be removed LDR R0,[R0,#ll_backwards] LDR R1,[R1,#ll_backwards] B %BT01 20 LDR R14,[R0,#ll_backwards] CMP R14,#nullptr LDREQ R14,[R1,#ll_backwards] STR R14,[handle,#w_yoffset] ; if nullptr, none of the children (or its descendants) was un-optimized Pull "R0,R1,PC" LTORG ;.............................................................................. ; In handle -> window block ; Out borderlinked flags set up: ; EQ => border will be block-copied with the work area ; NE => border will be dealt with separately isborderlinked Entry "R0,R1,cx0,cy0,cx1,cy1,x0,y0,x1,y1" BL hasfocus_changing LDREQ R14,[handle,#w_flags] LDREQ R2,[handle,#w_old_flags] EOREQ R14,R14,R2 TSTEQ R14,#wf_iconbits ; can't link border if focus or border flags are changing BNE %FT90 ADD R14,handle,#w_wax0 LDMIA R14,{cx0,cy0,cx1,cy1,x0,y0} SUB x1,cx1,cx0 ; x1,y1 = new size of window SUB y1,cy1,cy0 ; x0,y0 = new scroll posns ADD R14,handle,#w_old_wax0 LDMIA R14,{R0,R1,cx0,cy0,cx1,cy1} ; SUB R14,cx0,R0 ; R0 = old x0 CMP R14,x1 SUB R14,cy0,R1 ; cy0 = old y1 CMPEQ R14,y1 CMPEQ cx1,x0 ; cx1 = old scx CMPEQ cy1,y0 ; cy1 = old scy 90 [ No32bitCode STR PC,borderlinked | MRS R14,CPSR STR R14,borderlinked ] EXIT LTORG ;.............................................................................. ; In R0 -> list head of source data ; R1 -> list head of destination ; Out list in [R0] copied to [R1], with correct offsets for the new list copy_new_links_to_old ROUT Push "handle,LR" ; Debug opn,"copy_new_links_to_old",R0,R1 ADD R2,R1,#lh_indicator ; R2 = forward link for next window ADD R3,R1,#lh_backwards ; R3 = pointer to previous backwards pointer LDR handle,[R0,#lh_backwards] ; handle = first window + w_active_link, or list head 01 CMP handle,R0 ; stop when we get back to the list head BEQ %FT02 ADD R14,handle,#w_old_link - w_active_link STR R14,[R3] ; previous back pointer -> this window STR R2,[R14,#ll_forwards] ; this window's forward pointer -> previous link (or head) ; Debug opn,"prev. backwards set up",R3,R14 ; Debug opn,"this forwards set up",R14,R2 ADD R3,R14,#ll_backwards ; R3 -> next backwards pointer MOV R2,R14 ; R2 = forwards pointer to put in next link LDR handle,[handle,#ll_backwards] B %BT01 02 STR R2,[R1,#lh_forwards] ; head forwards -> last window visited (or head itself) STR R1,[R3] ; previous backwards -> list head itself ; Debug opn,"final backwards set up",R3,R1 ; Debug opn,"final forwards set up",R1,R2 Pull "handle,PC" ;.............................................................................. ; In handle -> window whose 'open' is to be flushed int_flush_open ROUT Push "LR" Debug opn,"int_flush_open",handle MOV R0,#borderrects BL loserects ; just in case BL losewindowrects ; ditto ; unless window is re-opening (ie. it was and still is open), we've practically finished LDR R14,[handle,#w_flags] LDR R0,[handle,#w_old_flags] ; Debug opn, "int_flush_open: old/new flags:", R0, R14 AND R14,R0,R14 TST R14,#ws_open ; DebugIf NE, opn, "int_flush_open: handle staying open:", handle ; DebugIf EQ, opn, "int_flush_open: handle NOT staying open:", handle BLEQ invalidate_oldnew BEQ %FT80 ; check for invalidation of border areas - if we're only scrolling, we may be able to keep parts of the border valid BL hasfocus_changing ; NE => borders need redrawing due to ws_hasfocus turning on/off [ IconiseButton :LAND: ChildWindows BLEQ iconise_changing ; NE => borders need redrawing due to iconise button / window stack dependency ] ADDEQ R14,handle,#w_old_wax0 ; compare old and new work area coords LDMEQIA R14,{x0,y0,x1,y1} ADDEQ R14,handle,#w_wax0 ; check old work area coords LDMEQIA R14,{cx0,cy0,cx1,cy1} [ TrueIcon3 TEQEQ x0,cx0 TEQEQ x1,cx1 TEQEQ y1,cy1 ; unless coords are the same [ No32bitCode STR PC,isborderok ; we invalidate all border areas anyway | MRS R14,CPSR STR R14,isborderok ] BNE %FT02 TEQEQ y0,cy0 BNE %FT06 ; special case: window being resized in vertical direction only | TEQEQ x0,cx0 TEQEQ y0,cy0 TEQEQ x1,cx1 TEQEQ y1,cy1 ; unless all coords are the same [ No32bitCode STR PC,isborderok ; we invalidate all border areas anyway | MRS R14,CPSR STR R14,isborderok ] BNE %FT02 ] ; get border rectangles, that were and still are valid and visible BL oldvisibleouterportion ; get previously-visible outer portion BL subwindowrect ; subtract work area (cx0..cy1 are still set up from above) BL visible_knockout ; clip to still-visible outer portion ; MOV R0,#windowrects ; MOV R1,#oldinvalidrects ; must also have been valid to begin with ; BL subrects ; NOTE: there's no need to do this, since oldinvalidrects is a subset of invalidrects MOV R0,#windowrects MOV R1,#invalidrects ; and still be valid at the end (NB: we haven't yet called invalidate_oldnew) BL subrects ; some border areas that aren't changing can be affected by other border bits turning on/off ; icons are numbered clockwise from the top-left: ; 1=back,2=quit,3=title,4=toggle,5=vscroll,6=size,7=hscroll LDR R1,[handle,#w_flags] ; R1 = new flag settings LDR R0,[handle,#w_old_flags] EOR R0,R1,R0 ; R0 = flags that have changed [ togglebits LDR R14, = wf_iconbits :OR: ws_toggled2 ANDS R0, R0, R14 | ANDS R0,R0,#wf_iconbits ] BEQ %FT10 ; common case - no change in flags Push "R0,R1" ADD R14,handle,#w_x0 LDMIA R14,{cx0,cy0,cx1,cy1} ; if flags have changed, we must clip to the new outer portion as well MOV R0,#windowrects MOV R1,R0 BL intrect Pull "R0,R1" ; check title / v-scroll / h-scroll for other bits that cause them to be resized MOV R2,#3 ; see if title bar is resizing BL check_redraw_border MOV R2,#5 ; see if v-scrollbar is resizing BL check_redraw_border MOV R2,#7 ; see if h-scrollbar is resizing BL check_redraw_border [ togglebits ; special case: check for toggle icon changing when window does not (it *can* happen with shift-toggle!) TST R1, #wf_icon4 TSTNE R0, #ws_toggled2 BEQ %FT08 Push "R0,R1" MOV R0,#4 BL calc_w_iconposn Push "x0,y0,x1,y1" Pull "cx0,cy0,cx1,cy1" BL subwindowrect Pull "R0,R1" 08 ] ; special case: check for back/quit changing places (this won't affect the title bar, so needs separate treatment) AND R14,R1,#wf_icon1 :OR: wf_icon2 TEQ R14,#wf_icon1 TEQNE R14,#wf_icon2 ANDEQ R14,R0,#wf_icon1 :OR: wf_icon2 TEQEQ R14,#wf_icon1 :OR: wf_icon2 ; EQ => back/quit have changed places BNE %FT08 Push "R0,R1" TST R1,#wf_icon1 MOVNE R0,#1 MOVEQ R0,#2 BL calc_w_iconposn ; x0,y0,x1,y1 = screen position of size box Push "x0,y0,x1,y1" Pull "cx0,cy0,cx1,cy1" BL subwindowrect ; must redraw size box if it's changing and scrollbars aren't Pull "R0,R1" [ IconiseButton ; special case: check for toggle/iconise changing places (this won't affect the title bar, so needs separate treatment) 08 AND R14,R1,#wf_icon4 :OR: wf_icon2 TEQ R14,#wf_icon4 TEQNE R14,#wf_icon2 ANDEQ R14,R0,#wf_icon4 :OR: wf_icon2 TEQEQ R14,#wf_icon4 :OR: wf_icon2 ; EQ => toggle/iconise have changed places BNE %FT08 Push "R0,R1" TST R1,#wf_icon4 MOVNE R0,#4 MOVEQ R0,#8 BL calc_w_iconposn ; x0,y0,x1,y1 = screen position of size box Push "x0,y0,x1,y1" Pull "cx0,cy0,cx1,cy1" BL subwindowrect ; must redraw size box if it's changing and scrollbars aren't Pull "R0,R1" ] ; special case: check for size toggling on/off while the scrollbars don't change 08 TST R0,#wf_icon5 :OR: wf_icon7 BNE %FT10 TST R0,#wf_icon6 MOVNE R0,#6 ; h-scroll bar BLNE calc_w_iconposn ; x0,y0,x1,y1 = screen position of size box Push "x0,y0,x1,y1",NE Pull "cx0,cy0,cx1,cy1",NE BLNE subwindowrect ; must redraw size box if it's changing and scrollbars aren't ; knock out h-scrollbar if we've scrolled horizontally 10 LDR R14,[handle,#w_scx] ; see if h-scroll bar has changed LDR R0, [handle, #w_old_scx] TEQ R14,R0 BEQ %FT01 MOV R0,#7 ; h-scroll bar BL calc_w_iconposn ; x0,y0,x1,y1 = screen position of h-scrollbar LDR R14,left_width ;<<< LDRB R14,xborder ADD cx0,x0,R14 LDR R14,right_width SUB cx1,x1,R14 LDR R14,dx ADD cx0,cx0,R14 ; border is OK SUB cx1,cx1,R14 LDR R14,dy ADD cy0,y0,R14 SUB cy1,y1,R14 BL subwindowrect ; this bit isn't valid! 01 ; knock out v-scrollbar if we've scrolled vertically LDR R14,[handle,#w_scy] ; see if v-scroll bar has changed LDR R0, [handle, #w_old_scy] TEQ R14,R0 BEQ %FT01 MOV R0,#5 ; v-scroll bar BL calc_w_iconposn ;<< LDRB R14,yborder LDR R14,down_height ADD cy0,y0,R14 LDR R14,up_height SUB cy1,y1,R14 LDR R14,dy ADD cy0,cy0,R14 ; border is OK SUB cy1,cy1,R14 LDR R14,dx ADD cx0,x0,R14 SUB cx1,x1,R14 BL subwindowrect ; this bit isn't valid! [ TrueIcon3 B %FT02 06 ; Special case: window is being resized in vertical direction only: see if we can prevent an unnecessary title bar redraw LDR R1, [handle, #w_flags] ; R1 = new flag settings LDR R0, [handle, #w_old_flags] EOR R0, R1, R0 ; R0 = flags that have changed ANDS R0, R0, #wf_iconbits BNE %FT02 ; furniture changing - cop out and invalidate everything TEQ R1, #wf_icon3 BEQ %FT02 ; no title bar, so no point in optimising it ; get border rectangles, that were and still are valid and visible BL oldvisibleouterportion ; get previously-visible outer portion BL subwindowrect ; subtract work area (cx0..cy1 are still set up from above) BL visible_knockout ; clip to still-visible outer portion ; MOV R0,#windowrects ; MOV R1,#oldinvalidrects ; must also have been valid to begin with ; BL subrects ; NOTE: there's no need to do this, since oldinvalidrects is a subset of invalidrects MOV R0,#windowrects MOV R1,#invalidrects ; and still be valid at the end (NB: we haven't yet called invalidate_oldnew) BL subrects ; reduce to border rectangles that are staying the same ADD R14, handle, #w_x0 LDMIA R14, {cx0, cy0, cx1, cy1} LDR cy0, [handle, #w_way1] ; cx0-cy1 = top row MOV R0, #windowrects MOV R1, #windowrects BL intrect ; don't optimise anything that isn't in the top row LDR R0, [handle, #w_flags] TST R0, #wf_icon4 ; if there's a toggle-size icon, it may have changed to reflect whether window is full-size or not MOVNE R0, #4 BLNE calc_w_iconposn ; x0-y1 = screen position of toggle box Push "x0, y0, x1, y1", NE Pull "cx0, cy0, cx1, cy1", NE BLNE subwindowrect ] 01 ; transfer the list to 'borderrects' - the list of rectangles to be re-validated in the border area (work area scrolled) 02 ; [ debugopn ; Debug opn, "Border rectangles to re-validate:" ; Push "R0-R12, R14" ; MOV R0, #windowrects ; BL listrects ; Pull "R0-R12, R14" ; ] LDR R0,rlinks+borderrects LDR R1,rlinks+windowrects STR R0,rlinks+windowrects STR R1,rlinks+borderrects ; swap the lists! ; work out offset from old window posn to new (work area coords!) ; also work out whether size or scroll bars are changing - ie. can we block-copy the borders together with the work area ; NB: if any border areas are being turned on or off, we also can't link the borders BL hasfocus_changing ; can't link borders if focus bit is changing [ IconiseButton :LAND: ChildWindows BLEQ iconise_changing ] LDREQ R2,[handle,#w_old_flags] LDREQ R3,[handle,#w_flags] EOREQ R14,R2,R3 TSTEQ R14,#wf_iconbits ; EQ => borders haven't been altered [ togglebits TSTEQ R14,#ws_toggled2 ] ADD R14,handle,#w_wax0 LDMIA R14,{cx0,cy0,cx1,cy1,x0,y0} SUB x1,cx1,cx0 ; x1,y1 = new size of window SUB y1,cy1,cy0 ; x0,y0 = new scroll posns ADD R14,handle,#w_old_wax0 LDMIA R14,{R0,R1,cx0,cy0,cx1,cy1} SUB R14,cx0,R0 ; R0 = old x0 CMPEQ R14,x1 SUBEQ R14,cy0,R1 ; cy0 = old y1 CMPEQ R14,y1 CMPEQ cx1,x0 ; cx1 = old scx CMPEQ cy1,y0 ; cy1 = old scy ; LDR x0,[handle,#w_wax0] ; new x0 LDR y0,[handle,#w_way1] ; new y1 LDR x1,[handle,#w_scx] ; new scx LDR y1,[handle,#w_scy] ; new scy ; SUB cx0,R0,cx1 ; x <- x-scx (old) SUB cy0,cy0,cy1 ; y <- y-scy (old) SUB cx1,x0,x1 ; x <- x-scx (new) SUB cy1,y0,y1 ; y <- y-scy (new) SUB x0,cx1,cx0 ; x-offset SUB y0,cy1,cy0 ; y-offset STR x0,[handle,#w_xoffset] STR y0,[handle,#w_yoffset] STR x0,xoffset ; for int_translatelist STR y0,yoffset [ No32bitCode STR PC,borderlinked ; save flag status | MRS R14,CPSR STR R14,borderlinked ] ; [ debugopn ; Debug opn, "borderrects before invalidate_oldnew:" ; Push "R0-R12, R14" ; MOV R0, #borderrects ; BL listrects ; Pull "R0-R12, R14" ; ] ; invalidate old and new visible work areas (will revalidate later on, when rectangles are copied) ; NB: child windows still in the 'opening' list are clipped out of the old and new visible areas BL invalidate_oldnew ; [ debugopn ; Debug opn, "borderrects after invalidate_oldnew:" ; Push "R0-R12, R14" ; MOV R0, #borderrects ; BL listrects ; Pull "R0-R12, R14" ; ] ; get the old visible portion (with or without scroll bars etc.) LDR R14,borderlinked [ No32bitCode TEQP R14,#0 ; restore status | MSR CPSR_f,R14 ] ADDEQ R14,handle,#w_old_x0 ADDNE R14,handle,#w_old_wax0 LDMIA R14,{x0,y0,x1,y1} BL oldvisibleportion_x0y0x1y1 ; get correct amount of window MOV R0,#windowrects MOV R1,#oldinvalidrects ; get rid of OLD invalid rectangles BL subrects BL oldsubtract_openingchildren BL int_translatelist ; translate coords, moving to oldwindowrects MOV R0,#oldwindowrects BL subtract_openingchildren ; ignore bits that are being done separately LDR R14,borderlinked [ No32bitCode TEQP R14,#0 ; restore status | MSR CPSR_f,R14 ] ADDEQ R14,handle,#w_x0 ADDNE R14,handle,#w_wax0 LDMIA R14,{x0,y0,x1,y1} BL visibleportion_x0y0x1y1 ; new visible list (WITHOUT subtracting invalid rectangles) [ ThreeDPatch BL CheckRedraw3DBorders ] ; clip old visible region to the new one, and stash the block-copy rectangles for later MOV R0,#oldwindowrects MOV R1,#windowrects BL intrects BL losewindowrects ; keep hold of list of block-copy rectangles - we'll need those later LDR R14,rlinks + oldwindowrects STR R14,[handle,#w_oldwindowrects] ; Debug opn, "rlinks_oldwindowrects copied to [handle,#w_oldwindowrects] :", R14 MOV R14,#nullptr STR R14,rlinks + oldwindowrects ; ; if border unlinked, but in same place (ie. scrolling) ; mark borders valid, except for the relevant scroll bar(s) which have already been removed from the list ; LDR R14,borderlinked [ No32bitCode TEQP R14,#0 ; exit if border linked | MSR CPSR_f,R14 ] BEQ %FT01 LDR R14,isborderok ; always redraw border if it toggled [ No32bitCode TEQP R14,#0 ; set flags | MSR CPSR_f,R14 ] ; ; [ debugopn ; Debug opn, "About to revalidate border - listing invalidrects and borderrects" ; Push "R0-R12, R14" ; MOV R0, #invalidrects ; BL listrects ; MOV R0, #borderrects ; BL listrects ; Pull "R0-R12, R14" ; ] MOVEQ R0,#invalidrects ; mark border bits valid again MOVEQ R1,#borderrects BLEQ subrects ; 01 MOV R0,#borderrects BL loserects ; skip straight to here if window wasn't / isn't open 80 Debug opn,"int_flush_open exitting" Pull "PC" [ ThreeDPatch CheckRedraw3DBorders ROUT Push "lr" [ debugthreedpatch Debug threedpatch,"Entering CheckRedraw3DBorders" ADD cx0,handle,#w_wax0 LDMIA cx0,{cx0-cy1} Debug threedpatch,"new work area :",cx0,cy0,cx1,cy1 ADD cx0,handle,#w_old_wax0 LDMIA cx0,{cx0-cy1} Debug threedpatch,"old work area :",cx0,cy0,cx1,cy1 ] LDR r14,ThreeDFlags TST r14,#ThreeDFlags_Use3DBorders Pull "pc",EQ LDR r14,[handle,#w_taskhandle] CMP r14,#-1 BEQ %FT02 LDRB r14,[handle,#w_wbcol] TEQ r14,#1 Pull "pc",NE LDRB r14,[handle,#w_flags2] AND r14,r14,#wf2_no3Dborder :OR: wf2_force3Dborder TEQ r14,#wf2_no3Dborder Pull "pc",EQ TEQ r14,#wf2_force3Dborder BEQ %FT02 LDR r14,[handle,#w_flags] TST r14,#&70000000 TSTEQ r14,#&00000020 [ No3DChildWindows LDREQ r14,[handle,#w_parent] CMPEQ r14,#-1 ; check if it's a top level window ] Pull "pc",NE 02 ADD x0,handle,#w_old_wax0 LDMIA x0,{x0-y1} ADD cx0,handle,#w_wax0 LDMIA cx0,{cx0-cy1} LDR lr,xoffset ADD x0,x0,lr ADD x1,x1,lr LDR lr,yoffset ADD y0,y0,lr ADD y1,y1,lr MOV r0,#0 ; number of rectangles to invalidate CMP x0,cx0 ; if NE then mark new left border as invalid MOVNE r1,cx1 ADDNE cx1,cx0,#4 Push "cx0-cy1",NE MOVNE cx1,r1 ADDNE r0,r0,#1 ; if GT then mark old left border as invalid MOVGT r1,x1 ADDGT x1,x0,#4 Push "x0-y1",GT MOVGT x1,r1 ADDGT r0,r0,#1 CMP x1,cx1 ; if NE then mark new right border as invalid MOVNE r1,cx0 SUBNE cx0,cx1,#4 Push "cx0-cy1",NE MOVNE cx0,r1 ADDNE r0,r0,#1 ; if LT then mark old right border as invalid MOVLT r1,x0 SUBLT x0,x1,#4 Push "x0-y1",LT MOVLT x0,r1 ADDLT r0,r0,#1 CMP y0,cy0 ; if NE then mark new bottom border as invalid MOVNE r1,cy1 ADDNE cy1,cy0,#4 Push "cx0-cy1",NE MOVNE cy1,r1 ADDNE r0,r0,#1 ; if GT then mark old bottom border as invalid MOVGT r1,y1 ADDGT y1,y0,#4 Push "x0-y1",GT MOVGT y1,r1 ADDGT r0,r0,#1 CMP y1,cy1 ; if NE then mark new top border as invalid MOVNE r1,cy0 SUBNE cy0,cy1,#4 Push "cx0-cy1",NE MOVNE cy0,r1 ADDNE r0,r0,#1 ; if LT then mark old top border as invalid MOVLT r1,y0 SUBLT y0,y1,#4 Push "x0-y1",LT MOVLT y0,r1 ADDLT r0,r0,#1 00 SUBS R0,R0,#1 Pull "pc",LT Pull "cx0-cy1" Push "r0" BL subwindowrect Pull "r0" B %BT00 ] ;.............................................................................. ; In handle -> window to consider ; Out NE => borders need redrawing due to ws_hasfocus bit changing hasfocus_changing Entry "R1,R2" LDR R14,[handle,#w_old_flags] LDR R1,[handle,#w_flags] AND R2,R14,R1 EOR R14,R14,R1 TST R14,#ws_hasfocus TSTNE R2,#wf_iconbits ; we can safely ignore this if window has no borders EXIT ;.............................................................................. [ IconiseButton :LAND: ChildWindows ; In handle -> window to consider ; Out NE => borders need redrawing due to iconise button dis/appearing due to window stack change iconise_changing Entry "R0-R2" LDR R14, [handle, #w_old_flags] LDR R1, [handle, #w_flags] AND R0, R14, R1 LDR R14, [handle, #w_old_parent] LDR R1, [handle, #w_parent] CMP R14, #nullptr ; if we're changing parents to/from the top-level stack, CMPNE R1, #nullptr ; iconise button may be switching on or off TOGPSR Z_bit, R2 ; NE => one or both stacks are -1 TEQNE R1, R14 ; NE => just one of them is TSTNE R0, #wf_icon2 ; we can safely ignore cases where the window can't have an iconise button EXIT ] ;.............................................................................. ; In R0 = flags being altered ; R1 = new flags ; R2 = icon index of icon to consider ; handle -> window block ; [rlinks,#windowrects] = rectangles that are to be re-validated within the border ; Out top/right/bottom border removed from list if relevant icon's position is changing ; cx0..cy1,x0..y1 corrupted check_redraw_border ROUT Push "R0-R1,LR" MOV R14,#wf_icon1 :SHR: 1 MOV R14,R14,LSL R2 ; R14 = relevant flag bit Debug opn,"Changing/new/testing",R0,R1,R14 TST R1,R14 Pull "R0-R1,PC",EQ ; must be present TST R0,R14 Pull "R0-R1,PC",NE ; and not changing MOV R0,R2 ; R0 = border icon handle (3=title,5=vscroll,7=hscroll) LDR R1,[handle,#w_old_flags] ADD R14,handle,#w_old_x0 LDMIA R14,{cx0,cy0,cx1,cy1} BL calc_w_iconposn_R1 ; x0,y0,x1,y1 = old position of icon (ignoring snazzy stuff wrt. child windows) Debug opn,"Old position of icon",R0,x0,y0,x1,y1 Push "x0,y0,x1,y1" LDR R1,[handle,#w_flags] ADD R14,handle,#w_x0 LDMIA R14,{cx0,cy0,cx1,cy1} BL calc_w_iconposn_R1 ; x0,y0,x1,y1 = new position of icon (ignoring snazzy stuff wrt. child windows) Debug opn,"New position of icon",R0,x0,y0,x1,y1 Pull "cx0,cy0,cx1,cy1" TEQ x0,cx0 TEQEQ y0,cy0 TEQEQ x1,cx1 TEQEQ y1,cy1 Pull "R0-R1,PC",EQ ; no change ADD R14,handle,#w_x0 LDMIA R14,{cx0,cy0,cx1,cy1} ; redraw relevant border if its position has changed CMP R0,#5 LDRLO cy0,[handle,#w_way1] ; top border (3) LDREQ cx0,[handle,#w_wax1] ; right border (5) LDRHI cy1,[handle,#w_way0] ; bottom border (7) Debug opn,"Invalidating border rectangle",cx0,cy0,cx1,cy1 BL subwindowrect Pull "R0-R1,PC" ;.............................................................................. ; mark old and new visible areas invalid invalidate_oldnew ROUT EntryS [ Twitter BL oldvisibleoutertwitter ; take account of antitwitter when building rects | BL oldvisibleouterportion ; remains in windowrects list ] MOV R0,#windowrects BL oldsubtract_openingchildren ; subtract children that are going to be done separately BL markinvalidrects ; add to invalidrects list (ie. new set) BL visibleouterportion MOV R0,#windowrects BL subtract_openingchildren ; subtract children that are going to be done separately BL markinvalidrects BL losewindowrects EXITS ; MUST PRESERVE FLAGS ;;----------------------------------------------------------------------------- ;; getparentbounds ;; Entry: cx0 -> parent window, or = nullptr ;; handle -> child window ;; Exit: cx0,cy0,cx1,cy1 = bounding box of parent or screen ;;----------------------------------------------------------------------------- getparentbounds ROUT Push "x0,y0,LR" CMP cx0,#nullptr ADREQ R14,scrx0 LDMEQIA R14,{cx0,cy0,cx1,cy1} Pull "x0,y0,PC",EQ LDR R14,[handle,#w_flags] ; if child window lives in parent's border, TST R14,#wf_inborder ADDNE R14,cx0,#w_x0 LDMNEIA R14,{cx0,cy0,cx1,cy1} ; bounding box is just the parent's window outline Pull "x0,y0,PC",NE LDR x0,[cx0,#w_wax0] LDR R14,[cx0,#w_scx] SUB x0,x0,R14 LDR y0,[cx0,#w_way1] LDR R14,[cx0,#w_scy] SUB y0,y0,R14 ; x0,y0 = work area origin ADD R14,cx0,#w_wex0 LDMIA R14,{cx0,cy0,cx1,cy1} ADD cx0,cx0,x0 ADD cy0,cy0,y0 ADD cx1,cx1,x0 ADD cy1,cy1,y0 LDR R14,dx ; expand box by 1 pixel all round SUB cx0,cx0,R14 ; this allows a window with a thin border to butt up against the top-left ADD cx1,cx1,R14 LDR R14,dy SUB cy0,cy0,R14 ADD cy1,cy1,R14 Pull "x0,y0,PC" ] ;;----------------------------------------------------------------------------- ;; topmost_window ;; Entry: <nothing> ;; Exit: R0=handle of topmost window (or 0 if not windows) flags preserved ;; This function is used mainly by hotkey processing code. ;;----------------------------------------------------------------------------- topmost_window EntryS LDR R0,activewinds+lh_forwards LDR R14,[R0,#ll_forwards] CMP R14,#nullptr MOVEQ R0,#0 SUBNE R0,R0,#w_active_link Rel R0,R0,NE EXITS ;;----------------------------------------------------------------------------- ;; Wimp_BlockCopy ;; Entry: R0 = window handle ;; R1-R4 = source rectangle (window-relative coords) ;; R5,R6 = destination rectangle lower-left (window-relative coords) ;;----------------------------------------------------------------------------- SWIWimp_BlockCopy MyEntry "BlockCopy" MOV handle,R0 BL checkhandle_owner ; drops all the way through if V set! BVS ExitWimp [ ChildWindows BL int_flush_opens ; wimp out for now ] Push "R1-R6" ; leave on stack for later SUB R5,R5,R1 ; x-offset SUB R6,R6,R2 ; y-offset STR R5,xoffset STR R6,yoffset pullx "x0,y0,x1,y1" [ ThreeDPatch BLVC int_visibleinner_ignore3Dboder_x0y0x1y1 ; [windowrects] = visible part | BLVC int_visibleinner_x0y0x1y1 ; [windowrects] = visible part ] MOVVC R0,#windowrects MOVVC R1,#invalidrects BLVC subrects BLVC int_translatelist ; [oldwindowrects] = translated list BLVC visibleinnerportion MOVVC R0,#oldwindowrects ; clip translated list to vis. window MOVVC R1,#windowrects BLVC intrects Pull "cx0,cy0,cx1,cy1,x0,y0" SUB R14,cx1,cx0 ADD x1,x0,R14 ; coords of new rectangle SUB R14,cy1,cy0 ADD y1,y0,R14 BLVC int_force_redraw ; mark new rectangles invalid BLVC int_blockcopy ; may re-validate some rectangles B ExitWimp [ ThreeDPatch CheckIfWindowRequires3DBorders ROUT Push "lr" LDR r14,ThreeDFlags TST r14,#ThreeDFlags_Use3DBorders BEQ %FT10 ; no border TST r14,#ThreeDFlags_TexturedMenus BEQ %FT01 LDR r14,[handle,#w_taskhandle] CMP r14,#-1 Pull "pc",EQ ; it's a menu so needs a border 01 LDRB r14,[handle,#w_wbcol] TEQ r14,#1 BNE %FT10 ; no border LDRB r14,[handle,#w_flags2] AND r14,r14,#wf2_no3Dborder :OR: wf2_force3Dborder TEQ r14,#wf2_no3Dborder BEQ %FT10 ; no border TEQ r14,#wf2_force3Dborder Pull "pc",EQ ; force border on LDR r14,[handle,#w_flags] TST r14,#&70000000 TSTEQ r14,#&00000020 [ No3DChildWindows LDREQ r14,[handle,#w_parent] CMPEQ r14,#-1 ; check if it's a top level window ] Pull "pc" ; if it's eq here then border needed, else not needed 10 CMP pc,#0 Pull "pc" ] ; ; Entry: [windowrects] = visible rectangles of old block ; [xoffset], [yoffset] = amount to add in to the coordinates ; Exit: [oldwindowrects] contains the correct rectangles, translated ; invalid list is subtracted from list ; int_translatelist Push "LR" [ :LNOT: ChildWindows MOV R0,#windowrects MOV R1,#invalidrects ; this is now done by the caller BL subrects ] ; ; copy this list to 'oldwindowrects' ; LDR R0,rlinks+oldwindowrects LDR R1,rlinks+windowrects STR R0,rlinks+windowrects STR R1,rlinks+oldwindowrects ; swap the lists! ; ; translate rectangle list to new position ; LDR x0,xoffset LDR y0,yoffset ; Push "handle,userblk" SetRectPtrs ; MOV R1,#oldwindowrects B openwlp1end openwlp1 getxy R1,cx,cy ADD cx0,cx0,x0 ADD cy0,cy0,y0 ADD cx1,cx1,x0 ADD cy1,cy1,y0 putxy R1,cx,cy openwlp1end LDR R1,[rectlinks,R1] CMP R1,#nullptr BNE openwlp1 ; Pull "handle,userblk,PC" ;.................................................................................... [ ChildWindows ; Entry: oldwindowrects = source rectangle list, translated already ; x/yoffset = translation amount ; handle = window handle of relevant window ; no opens are pending at the moment ; Exit: rectangles fudged into the relevant window, and int_blockcopy_all called ; R0,R1,cx0..cy1,x0..y1 corrupted int_blockcopy ROUT Debug opn,"int_blockcopy" ADR R2,xoffset LDMIA R2,{x0,y0} ADD R2,handle,#w_xoffset STMIA R2,{x0,y0} LDR R2,rlinks+oldwindowrects STR R2,[handle,#w_oldwindowrects] MOV R2,#nullptr STR R2,rlinks+oldwindowrects ADRL R1,openingwinds+lh_forwards-ll_forwards ; top-level window LDR R0,[R1,#ll_forwards] ASSERT ll_forwards = 0 :LAND: ll_backwards = 4 ADD R2,handle,#w_opening_link STMIA R2,{R0,R1} STR R2,[R0,#ll_backwards] STR R2,[R1,#ll_forwards] ; drop through to int_blockcopy_all ;.................................................................................... ; Entry: openingwinds = list of windows being opened ; for each window (handle) in list: ; [handle,#w_oldwindowrects] = source rectangle list, translated already ; [handle,#w_x/yoffset] = translation amount ; Exit: if possible, rectangles will be block-copied to the new position int_blockcopy_all Push "handle,userblk,LR" Debug opn,"int_blockcopy_all" [ :LNOT: Autoscr ; leave graphics window / dragbox until later LDR R14,commandflag ; KJB: check we're actually in TEQ R14,#cf_dormant ; the desktop BLEQ defaultwindow ; set to whole screen BL forcedrag_off ; remove drag rectangle ] SetRectPtrs blcopynext_outer ; Debug opn,"blcopynext_outer" ; MOV R14,#nullptr STR R14,oldlink ; no rectangles to get rid of so far LDR R2,openingwinds + lh_forwards blcopynext_window ; Debug opn,"blcopynext_window" ; LDR R14,[R2,#ll_forwards] CMP R14,#nullptr BEQ blcopyend_window ; we got to the end - should we try again? ADD R1,R2,#w_oldwindowrects - w_opening_link SUB R1,R1,rectlinks ; bodge so [rectlinks,R1] -> next rectangle blcopynext ; Debug opn,"blcopynext" ; MOV R14,R1 LDR R1,[rectlinks,R1] CMP R1,#nullptr BEQ blcopyend ; we found a rectangle - see if we can copy it ; Debug opn,"Try to block-copy old/rectangle",R14,R1 ; STR R14,oldlink ; check to see whether it would trash any other rectangles before block-copying it ; R1 = rectangle to consider ; R2 = handle + w_opening_link of the first window Push "R1,R2" ; remember R1,R2 for the outer loop ADD R14,R2,#w_xoffset - w_opening_link LDMIA R14,{x0,y0} ADR R14,xoffset ; x/yoffset hold offsets for the candidate rectangle STMIA R14,{x0,y0} getxy R1,cx,cy ; inner loop - scan all rectangles from the beginning LDR x0,openingwinds + lh_forwards blcopynext_inner ; Debug opn,"blcopynext_inner" ; LDR R14,[x0,#ll_forwards] CMP R14,#nullptr BEQ goblockcopy ; no rectangles intersect - go ahead and block-copy it ADD R14,x0,#w_xoffset - w_opening_link LDMIA R14,{x1,y1} Push "x0,x1,y1" ; parameters for the current window (inner loop) ADD R0,x0,#w_oldwindowrects - w_opening_link SUB R0,R0,rectlinks ; bodge so [rectlinks,R0] -> next rectangle 01 LDR R0,[rectlinks,R0] CMP R0,#nullptr BEQ %FT04 ; try next window CMP R0,R1 ; ignore the candidate rectangle itself BEQ %BT01 getxy R0,x,y LDR R14,[SP,#4] SUB x0,x0,R14 ; go back to old posn SUB x1,x1,R14 LDR R14,[SP,#8] SUB y0,y0,R14 SUB y1,y1,R14 CMP x0,cx1 ; see if new tramples on old CMPLT cx0,x1 CMPLT y0,cy1 CMPLT cy0,y1 BGE %BT01 ; continue if rectangles don't intersect ; this rectangle couldn't be copied - let's try the next one ADD SP,SP,#12 Pull "R1,R2" B blcopynext 04 Pull "x0,x1,y1" LDR x0,[x0,#ll_forwards] B blcopynext_inner ; block-copy the rectangle goblockcopy ; Debug opn,"goblockcopy" ; LDR R0,xoffset CMP R0,#0 LDR R14,yoffset CMPEQ R14,#0 BEQ %FT10 ; just mark valid if no move SUB x0,cx0,R0 SUB y0,cy0,R14 SUB x1,cx1,R0 SUB y1,cy1,R14 [ Autoscr LDRB R14, dragflag TEQ R14, #0 ; don't bother if not dragging BEQ %FT06 LDR R14, dragflags TST R14, #dragf_clip BNE %FT05 BL graphicswindow ; non-clipped dragboxes can also be plotted just in visible rectangles (reduces flicker) BL forcedrag_off ; corrupts flags B %FT06 05 LDR R14, draghandle ; for clipped dragboxes, check we're block-copying the right window Abs R14, R14 LDR R0, [sp, #1*4] ; get handle from stack SUB R0, R0, #w_opening_link TEQ R0, R14 BNE %FT06 Push "cx0, cy0, cx1, cy1, x0, y0, x1, y1" ASSERT :INDEX:tempworkspace = 0 ; now we must also restrict redraw to exclude the borders LDMIA wsptr, {cx0, cy0, cx1, cy1} ; get old visible area stored back in int_flush_opens CMP cx0, x0 MOVGT x0, cx0 ; x0 = max (cx0, x0) CMP cx1, x1 MOVLT x1, cx1 ; x1 = min (cx1, x1) CMP cy0, y0 MOVGT y0, cy0 ; y0 = max (cy0, y0) CMP cy1, y1 MOVLT y1, cy1 ; y1 = min (cy1, y1) CMP x1, x0 CMPGT y1, y0 ; don't plot anything if there's no work area in this rectangle BLGT graphicswindow BLGT forcedrag_off Pull "cx0, cy0, cx1, cy1, x0, y0, x1, y1" 06 BL defaultwindow ] Push "cx0" ; because Plot corrupts Plot 4,x0,y0 LDR R14,dx SUB x1,x1,R14 LDR R14,dy SUB y1,y1,R14 Plot 4,x1,y1 Pull "cx0" ASSERT rectcoords = R10 Push "rectcoords" LDR R10, [SP, #2*4] ; get R2 pushed above SUB R10, R10, #w_opening_link CallFilter copyfilter,nohandle Pull "rectcoords" Push "cx0" Plot 190,cx0,cy0 ; block copy! Pull "cx0" Debug opn,"Block-copied rectangle to",cx0,cy0,cx1,cy1 [ Autoscr LDRB R14, dragflag TEQ R14, #0 ; don't bother if not dragging BEQ %FT06 LDR R14, dragflags TST R14, #dragf_clip BNE %FT05 Push "cx0 - cy1" ; non-clipped dragboxes can also be plotted just in visible rectangles (reduces flicker) Pull "x0 - y1" ; use stack to shift values from cx0-cy1 to x0-y1 BL graphicswindow BL forcedrag_on ; corrupts flags B %FT06 05 LDR R14, draghandle ; for clipped dragboxes, check we're block-copying the right window Abs R14, R14 LDR R0, [sp, #1*4] ; get handle from stack SUB R0, R0, #w_opening_link TEQ R0, R14 BNE %FT06 ADD R14, R14, #w_wax0 ; now we must also restrict redraw to exclude the borders LDMIA R14, {x0, y0, x1, y1} ; get new visible area CMP cx0, x0 MOVGT x0, cx0 ; x0 = max (cx0, x0) CMP cx1, x1 MOVLT x1, cx1 ; x1 = min (cx1, x1) CMP cy0, y0 MOVGT y0, cy0 ; y0 = max (cy0, y0) CMP cy1, y1 MOVLT y1, cy1 ; y1 = min (cy1, y1) CMP x1, x0 CMPGT y1, y0 ; don't plot anything if there's no work area in this rectangle BLGT graphicswindow BLGT forcedrag_on 06 BL defaultwindow ] 10 MOV R0,#invalidrects MOV R1,R0 BL subrect ; mark cx0,cy0,cx1,cy1 valid ; free this rectangle, and remove from the list ADD SP,SP,#2*4 ; correct stack (we're starting again, so we don't need R1,R2) LDR R2,oldlink noblockcopy ; Debug opn,"noblockcopy" ; LDR R1,[rectlinks,R2] Debug opn,"Free old/rectangle",R2,R1 LDR R14,[rectlinks,R1] STR R14,[rectlinks,R2] ; remove from window's list, LDR R14,[rectlinks,#freerects] STR R14,[rectlinks,R1] STR R1,[rectlinks,#freerects] ; and add to free list B blcopynext_outer ; start again from the very beginning ; got to the end of a window - if it had no rectangles, remove it from the list (speeds up the inner loop) blcopyend ; Debug opn,"blcopyend" ; LDR R14,[R2,#w_oldwindowrects - w_opening_link] CMP R14,#nullptr LDRNE R2,[R2,#ll_forwards] BNE blcopynext_window ; go on to the next window Debug opn,"Remove window from opening list (no more rectangles)",R2 LDMIA R2,{x0,y0} STR x0,[y0,#ll_forwards] STR y0,[x0,#ll_backwards] MOV R14,#0 ; mark as not being in the chain STR R14,[R2,#ll_forwards] MOV R2,x0 ; don't load from the link - it's been reset! B blcopynext_window ; go on to the next window ; couldn't find ANY rectangles to copy ; if we haven't done them all, the best we can do (so far) is to simply drop one of the rectangles and carry on blcopyend_window Debug opn,"*** Couldn't copy any more",#oldlink LDR R2,oldlink CMP R2,#nullptr BNE noblockcopy blcopydone Debug opn,"int_blockcopy_all exitting" [ :LNOT: Autoscr BL forcedrag_on ; restore drag rectangle ] Pull "handle,userblk,PC" | ; ; Entry: [oldwindowrects] = source rectangle list, translated already ; [xoffset], [yoffset] = translation amount ; Exit: if possible, rectangles will be block-copied to the new position ; int_blockcopy Push "LR" ; BL defaultwindow ; set to whole screen BL forcedrag_off ; remove drag rectangle ; Push "userblk,handle" SetRectPtrs blcopynext MOV R1,#oldwindowrects bltrynext STR R1,oldlink ; to allow deletion LDR R1,[rectlinks,R1] CMP R1,#nullptr BEQ noblockcopy ; can't copy any more ; getxy R1,cx,cy MOV R0,#oldwindowrects blcmpnext LDR R0,[rectlinks,R0] CMP R0,#nullptr BEQ goblockcopy ; OK if no intersections TEQ R0,R1 BEQ blcmpnext ; OK to intersect yourself ; getxy R0,x,y LDR R14,xoffset SUB x0,x0,R14 ; go back to old posn SUB x1,x1,R14 LDR R14,yoffset SUB y0,y0,R14 SUB y1,y1,R14 ; CMP x0,cx1 ; see if new tramples on old CMPLT cx0,x1 CMPLT y0,cy1 CMPLT cy0,y1 BLT bltrynext ; can't copy this - intersects! B blcmpnext ; continue ; ; OK to copy - delete rectangle from list ; goblockcopy LDR R0,oldlink LDR R14,[rectlinks,R1] STR R14,[rectlinks,R0] ; delete from list LDR R14,[rectlinks,#freerects] STR R14,[rectlinks,R1] STR R1,[rectlinks,#freerects] ; and add to free list ; ; now block-copy the rectangle ; LDR R0,xoffset TEQ R0,#0 LDR R14,yoffset TEQEQ R14,#0 BEQ noactualcopy ; just mark valid if no move ; SUB x0,cx0,R0 SUB y0,cy0,R14 SUB x1,cx1,R0 SUB y1,cy1,R14 Push cx0 Plot 4,x0,y0 LDR R14,dx SUB x1,x1,R14 LDR R14,dy SUB y1,y1,R14 Plot 4,x1,y1 Pull cx0 ; CallFilter copyfilter,nohandle ; Push cx0 Plot 190,cx0,cy0 ; block copy! Pull cx0 ; noactualcopy MOV R0,#invalidrects MOV R1,R0 BL subrect ; mark cx0,cy0,cx1,cy1 valid B blcopynext ; noblockcopy Pull "userblk,handle" ; BL forcedrag_on ; restore drag rectangle ; MOV R0,#oldwindowrects ; just in case any are left BL loserects ; Pull "PC" ] ;;----------------------------------------------------------------------------- ;; Close_Window - remove window from the active list ;;----------------------------------------------------------------------------- SWIWimp_CloseWindow MyEntry "CloseWindow" ; LDR R0,[userblk] MOV handle,R0 [ ChildWindows BL checkhandle ; window need not be owned by this task | BL checkhandle_owner ; window must be owned by task ] BLVC nocaret ; R0,handle = rel/abs handles BLVC int_close_window ADDVC R14,handle,#w_wax0 LDMVCIA R14,{x0,y0,x1,y1} BLVC int_force_redraw ; make sure window is redrawn if reopened ; B ExitWimp ;............................................................................. ; In R0 = relative window handle of window being closed ; [caretdata+0] = relative window handle of window with caret ; Out [caretdata+0] = -1 if this window was closed ; [menucaretwindow] = -1 likewise nocaret Push "R0,R1,handle,LR" [ ChildWindows LDR handle,caretdata BL isparentof ; EQ if R0 is a parent of handle MOVEQ R0,handle | LDR R14,caretdata ; turn caret off if nec. TEQ R0,R14 ] MOVEQ R14,#nullptr STREQ R14,caretdata BLEQ focusoff ; NB close panes before tools [ ChildWindows BVS %FT01 LDR R0,[SP] ; restore R0 LDR handle,menucaretwindow ; check for previous owner of caret (before menu) being closed BL isparentof ; EQ if R0 is a parent of handle | LDR R14,menucaretwindow TEQ R0,R14 ] MOVEQ R14,#nullptr STREQ R14,menucaretwindow 01 MOV R14,#0 STR R14,caretscrollx STRVS R0,[R13] Pull "R0,R1,handle,PC" ;............................................................................. ; In handle = relative handle of window in question ; R0 = relative handle of what might be the parent ; Out EQ if R0 = handle, or its parent [ ChildWindows isparentof ROUT Push "R0,handle,LR" CMP handle,#nullptr BEQ %FT80 BL checkhandle ; if handle illegal, leave it to someone else! BVS %FT80 Abs R0,R0 01 TEQ handle,R0 BEQ %FT90 LDR handle,[handle,#w_parent] CMP handle,#nullptr BNE %BT01 80 CMP PC,#0 ; NE => R0 wasn't a parent of handle Pull "R0,handle,PC" 90 CMP R0,R0 ; EQ => R0 was a parent of handle Pull "R0,handle,PC" ] ;----------------------------------------------------------------------------- ; internal entry point - handle --> window definition ;----------------------------------------------------------------------------- [ Autoscr int_close_window ; if this was the autoscrolling window, or the window-relative dragbox window, ; turn off autoscrolling and/or dragging as appropriate Push "R0, R14" LDR R0, autoscr_state TST R0, #af_enable TOGPSR Z_bit, R0 ; EQ => autoscroll enabled LDREQ R0, autoscr_handle Abs R0, R0, EQ TEQ R0, handle ; EQ => autoscroll enabled for this window MOVEQ R0, #0 BLEQ int_autoscroll ; turn off autoscrolling LDR R0, dragtype TEQ R0, #0 LDRNE R0, dragflags TSTNE R0, #dragf_anchor :OR: dragf_clip TOGPSR Z_bit, R0 ; EQ => window-relative drag LDREQ R0, draghandle Abs R0, R0, EQ TEQ R0, handle ; EQ => window-relative drag for this window BLEQ nodragging ; turn off dragging Pull "R0, R14" int_close_window2 ; special entry point if window is due to be re-opened immediately afterwards | int_close_window ] Push "R1-R9,LR" ; must match stacking above Debug opn,"Closing window",handle ; BL checkredrawhandle [ ChildWindows BL int_mark_window_opening ; put onto openingwinds chain | Pull "R1-R9,PC",VS ; not actually needed ; ; all invalidation is now done in int_flush_opens ; [ Twitter BL visibleoutertwitter ; take account of antitwitter when building rects | BL visibleouterportion ; remains in windowrects list ] BL markinvalidrects ; add to invalidrects list BL losewindowrects ] ; ; if window was really open, remove handle from stack ; LDR R0,[handle,#w_flags] TST R0,#ws_open BEQ endclose ; ; update task priority based on number of open windows ; LDR R0,[handle,#w_taskhandle] CMP R0,#0 BLE %FT01 ; If a system window, just skip. LDR R0,[wsptr,R0] LDR R14,[R0,#task_windows] SUBS R14,R14,#1 STR R14,[R0,#task_windows] ; Decrement number. LDREQ R14,[R0,#task_priority] ; If reached 0, change priority. BICEQ R14,R14,#priority_windows STREQ R14,[R0,#task_priority] 01 ; delink window from activelist LDR R2,[handle,#w_active_link+ll_backwards] LDR R3,[handle,#w_active_link+ll_forwards] Debug child,"delink window: back/forwards =",R2,R3 STR R3,[R2,#ll_forwards] STR R2,[R3,#ll_backwards] ; ; NB: set window's parent to -1 (must do this in case the parent is later deleted) ; [ ChildWindows MOV R14,#nullptr STR R14,[handle,#w_parent] ] ; ; mark window as closed, and not top ; endclose LDR R0,[handle,#w_flags] BIC R0,R0,#ws_open:OR:ws_top ; unset both flags STR R0,[handle,#w_flags] ; Pull "R1-R9,PC" LTORG ;.............................................................................. ; In handle -> window to mark as being opened/closed ; Out window and all descendants added to openingwinds, if not already on it [ ChildWindows int_mark_window_opening Entry "R0,R1" MOV R14,#1 STRB R14,openspending LDR R14,[handle,#w_opening_link+ll_forwards] TEQ R14,#0 BLEQ int_mark_children ; stick window and descendants in openingwinds list (unless already in it) EXIT ;.............................................................................. ; We need to make sure that if a window is on the opening list, then so are all its descendents ; They may get removed by remove_children, but that's another story ; This routine assumes that the window on entry is NOT yet in the openingwinds list ; In: handle -> window to add to list ; Out: window and all descendants added to openingwinds list ; R0,R1 corrupted int_mark_children Entry "handle" ADRL R1,openingwinds+lh_forwards-ll_forwards ; stick this window in the opening list first LDR R0,[R1,#ll_forwards] ASSERT ll_forwards = 0 :LAND: ll_backwards = 4 ADD R14,handle,#w_opening_link STMIA R14,{R0,R1} STR R14,[R0,#ll_backwards] STR R14,[R1,#ll_forwards] Debug opn,"Stick handle in opening_link list",handle,R0,R1 LDR handle,[handle,#w_children + lh_forwards] ; makes no difference whether we traverse the old or new list 01 ASSERT ll_forwards = 0 LDR R14,[handle],#-w_active_link CMP R14,#nullptr EXIT EQ LDR R14,[handle,#w_opening_link + ll_forwards] TEQ R14,#0 BLEQ int_mark_children LDR handle,[handle,#w_active_link + ll_forwards] B %BT01 ] ;;----------------------------------------------------------------------------- ;; Redraw_Window - draw window outline and icons ;; Entry : if handle = redrawhandle, windowrects = bits to be redrawn ;; if not, redraw all of visible window ;; Exit : windowrects = list of rectangles in work area ;; reason code as for get_rectangle (ie. first call is done for you) ;;----------------------------------------------------------------------------- SWIWimp_RedrawWindow MyEntry "RedrawWindow" [ ChildWindows BL int_flush_opens ; if we get any, we'll have to redraw the whole window ] LDR handle,[userblk] LDR R1,redrawhandle [ debug LDR R14,rlinks + windowrects Debug child,"Wimp_RedrawWindow: handle,redrawhandle,windowrects",handle,R1,R14 ] TEQ handle,R1 STRNE handle,redrawhandle BL checkhandle_owner ; must preserve flags BVS ExitWimp BLNE visibleouterportion ; redraw entire window BL int_redraw_window B ExitGetRectangle ; same exit parameters ;----------------------------------------------------------------------------- ; internal entry point - called by Poll_Wimp sometimes ;----------------------------------------------------------------------------- [ ChildWindows backicon DCD &0D85 ; moved from the end quiticon DCD &0D84 toggleicon1 DCD &0D81 toggleicon2 DCD &0D82 ] int_redraw_window Push LR ; Rel R14,handle STR R14,redrawhandle Debug child,"Wimp_RedrawWindow",handle LDR R14,[handle,#w_taskhandle] Task R14,,"Redraw" ; page in window owner ; ; subtract child windows that are allowed to intrude on the border ; [ ChildWindows LDR R14,BPR_indication CMP R14,#BPR_continuelevel MOVLO R1,#wf_inborder BLLO subtract_children ; remove border child windows from the list ] ; ; use VDU 5 mode throughout ; SWI XOS_WriteI+5 ; VDU 5 mode LDR R14,[handle,#w_areaCBptr] STR R14,areaCBptr ; in case title is a sprite ; MOV R14,#-1 STR R14,hascaret ; -1 ==> icons do NOT have the caret ; ; set ecf origin to top-left of window border ; LDR R0,[handle,#w_x0] LDR R1,[handle,#w_y1] SUB R1,R1,#1 ; pointless really! SWI XOS_SetECFOrigin [ TrueIcon3 ; ; set up true colours ; BL setwindowcolours ] ; ; go through appropriate rectangles, drawing the window outline ; ; *** ; *** AWOOGA! AWOOGA! Filter Managers <0.19 will expect to find handle at this position on the stack ; *** Push "userblk,handle" ; MOV R1,#windowrects B endredrawoutlp ; rect ptrs set up there redrawoutlp getxy R1,x,y Debug child,"Redrawing rectangle",x0,y0,x1,y1 pullx "userblk,handle" ; used to be after BL forcedrag_off CallFilter rectanglefilter BL graphicswindow [ Autoscr LDR R14, dragflags TST R14, #dragf_clip ; clipped dragboxes must only be redrawn within their own window's work area BLEQ forcedrag_off ; remove drag box while updating | BL forcedrag_off ; remove drag box while updating ] ; Push "R1" ; ; ADD R14,handle,#w_wax0 LDMIA R14,{x0,y0,x1,y1} ; ; if w_tfcol = 255, and there are no border elements, then don't draw border at all ; LDRB R14,[handle,#w_tfcol] TEQ R14,#255 [ ChildWindows LDR R14,[handle,#w_flags] ; there's only NO border if these are off as well TSTEQ R14,#wf_iconbits ] BEQ doneborder ; skip the lot! ; ; draw border round work area (unless w_tfcol = 255) ; [ ChildWindows LDRB R14,[handle,#w_tfcol] TEQ R14,#255 BNE have_thin_border [ TrueIcon3 LDR R0, truetitlefg | MOV R0,#7 ; set black border in case toolsprites need it... ] BL window_fg B no_thin_border have_thin_border ] LDR R14,dx SUB x0,x0,R14 ADD x1,x1,R14 LDR R14,dy SUB y0,y0,R14 ADD y1,y1,R14 [ TrueIcon3 LDR R0, truetitlefg ; set title foreground colour CMP R0, #0 ; is foreground colour black? LDREQ R0, truewindowoutlinecolour ; if so, get window outline colour | LDRB R0,[handle,#w_tfcol] ; set title foreground colour ] BL window_fg BL hollowrectangle [ ChildWindows no_thin_border ] [ TrueIcon3 ; ; set title background colour ; LDR R14, [handle, #w_flags] TST R14, #ws_hasfocus LDREQ R0, truetitlebg LDRNE R0, truetitlebg2 STR R0, titlecolour ; title backgraound, irrespective of input focus BL window_bg | ; ; set title background colour and draw window border ; LDR R14,[handle,#w_flags] TST R14,#ws_hasfocus LDREQB R0,[handle,#w_tbcol] LDRNEB R0,[handle,#w_tbcol2] ; 'highlight' colour STRB R0,titlecolour BL window_bg ; ; if title is anti-aliased text, set up the font colours ; [ outlinefont LDR R14,systemfont TEQ R14,#0 ; is the system font anti-aliased? LDREQ R14,[handle,#w_titleflags] TSTEQ R14,#if_fancyfont | LDR R14,[handle,#w_titleflags] TST R14,#if_fancyfont ] [ ChildWindows BEQ %FT01 ;set => fancy font LDRB R1,titlecolour LDRB R2,[handle,#w_tfcol] TEQ R2,#&FF MOVEQ R2,#7 ; title text colour if 'no border' colour set must be black CMP R2,#&100 ; set NE again 01 | ;set => fancy font LDRNEB R1,titlecolour LDRNEB R2,[handle,#w_tfcol] ] ;clear => system font ;do nothing STRNEB R1,fontbackground STRNEB R2,fontforeground [ debug :LAND: debugfont BEQ redrawoutlp_done_tracing ] TraceK fcol, "redrawoutlp: fontbackground " TraceX fcol, R1 TraceNL fcol TraceK fcol, "redrawoutlp: fontforeground " TraceX fcol, R2 TraceNL fcol redrawoutlp_done_tracing [ {FALSE} BLNE setfontcolours ] ] ; ; draw icons surrounding window ; LDR R3,[handle,#w_flags] LDR R4,tool_list ; -> list of tools / = 0 if none TEQ R4, #0 ; Empty? BNE %FT01 ; No then jump LDR LR,tool_area TEQ LR,#0 ; Tool area empty? BLNE maketoollist ; No then rebuild tool_list LDRNE R4,tool_list 01 TEQ R4, #0 ; Empty? TSTNE R3, #ws_hasfocus ; does our window have the input focus? MOVNE R14, #tool_blank ; if so, get index of last icon ADDNE R4,R4,R14,LSR #1 ; r4 -> upper table half (=focus icons) [ TrueIcon3 LDR R14, titlecolour LDR R0, =&BBBBBB00 TEQ R0, R14 LDREQ R14, truetitlefg TEQEQ R14, #0 ; unless both colours are standard, LDRNEB R0, tinted_enable ; turn on tinting for this window STRNEB R0, tinted_window [ colourmoreborder BLNE forcetint_on ; turn on tinting for this window ] ] TST R3,#wf_icon1 BEQ %FT01 ; no back icon ; MOV R0,#iconposn_back BL calc_w_iconposn ; get bounding box for icon ; MOV R2,#windowicon_back BL plot_windowglyph ; plot a window glyph ADREQ R2,backicon LDREQ R1,=sysicon BLEQ drawicon_system ; preserves flags 01 TST R3,#wf_icon2 BEQ %FT01 ; no close icon ; MOV R0,#iconposn_close BL calc_w_iconposn ; preserve flags MOV R2,#windowicon_close BL plot_windowglyph LDREQ R1,=sysicon ADREQ R2,quiticon BLEQ drawicon_system ; preserves flags 01 TST R3,#wf_icon3 BEQ %FT01 ; ignore the title bar if one not being plotted ; MOV R0,#iconposn_title BL calc_w_iconposn ; setup bounding box ;Unless this is a title bar which expects to appear in a scalable ; font anyway, put the colours into the colour nybbles of the ; word, where seticonptrs expects to find them. LDR R1,[handle,#w_titleflags] ;Icon always has a border & is filled ORR R1, R1, #if_border :OR: if_filled [ :LNOT: TrueIcon3 TST R1, #if_fancyfont ;First clear out the top byte. BICEQ R1, R1, #&FF000000 LDREQB R2, fontforeground ORREQ R1, R1, R2, LSL #ib_fcol LDREQB R2, fontbackground ORREQ R1, R1, R2, LSL #ib_bcol ] ORR R1, R1, #15 :SHL: ib_buttontype ; pretend it's writeable, so that if this is a menu, we don't attempt keyboard shortcut justification Trace fcol, "redrawoutlp: title flags faked to ", X, R1 [ TrueIcon3 :LAND: :LNOT: colourmoreborder BL forcetint_on ] TEQ R4,#0 LDRNE R2,[R4,#tool_tbarlcap] TEQNE R2,#0 ; plot using sprites? BLNE dofunkytitlebar ; yes, sir-re bob! ADDEQ R2,handle,#w_title BLEQ drawicon_system ; take note of if_indirected et�. [ TrueIcon3 :LAND: :LNOT: colourmoreborder BL forcetint_off ] 01 TST R3,#wf_icon4 ; toggle doofer icon thingi? BEQ %FT01 ; MOV R0,#iconposn_toggle BL calc_w_iconposn ; bounding box of the toggle icon ; TEQ R4,#0 BEQ %FT05 ; ignore if not a sprite list setup ; LDR R14,border_iconselected CMP R14,#windowicon_toggle BNE %FT08 LDR R14,border_windowselected TEQ R14,handle BNE %FT08 [ togglebits TST R3,#ws_toggled :OR: ws_toggled2 | TST R3,#ws_toggled ] LDREQ R2,[R4,#tool_ptoggle] LDRNE R2,[R4,#tool_ptoggle1] B %FT09 08 [ togglebits TST R3,#ws_toggled :OR: ws_toggled2 | TST R3,#ws_toggled ] LDREQ R2,[R4,#tool_toggle] LDRNE R2,[R4,#tool_toggle1] 09 TEQ R2,#0 ; is a toggle sprite setup yet? BLNE draw_spriteglyph ; plot an suitable icon for the gadget then BNE %FT01 05 [ togglebits TST R3,#ws_toggled :OR: ws_toggled2 | TST R3,#ws_toggled ] ADREQ R2,toggleicon1 ADRNE R2,toggleicon2 LDR R1,=sysicon BL drawicon_system ; plot as a normal VDU 5 glyph otherwise [ IconiseButton 01 TST R3,#wf_icon2 ; have an iconise button iff we have a close button BEQ %FT01 LDR R0, [handle, #w_parent] CMP R0, #-1 BNE %FT01 ; but not if a child window LDRB R0, iconisebutton TEQ R0, #0 BEQ %FT01 ; or if configured off ; MOV R0,#iconposn_iconise BL calc_w_iconposn ; bounding box of the iconise icon MOV R2,#windowicon_iconise BL plot_windowglyph LDREQ R1,=sysicon ADREQL R2,iconiseicon BLEQ drawicon_system ; preserves flags ] 01 TST R3,#wf_icon5 BEQ novscroll ; [ ChildWindows Push "cx0,cy0,cx1,cy1" MOV R0,#iconposn_vscroll BL calc_w_iconposn2 ; x0..y1 = bounds of scroll region, cx0..cy1 = 'normal' bounds LDR R14,dy SUB R0,cy1,R14 CMP y0,R0 ; force within the 'normal' box MOVGT y0,R0 ADD R0,cy0,R14 CMP y1,R0 MOVLT y1,R0 ADD R0,y0,R14 CMP y1,R0 MOVLT y1,R0 ; Debug ,"calc_w_iconposn (v-scrollbar)",R3,x0,y0,x1,y1 Push "cy0" CMP y1,cy1 LDRLT R14,dy SUBLT cy0,y1,R14 BLLT scroll_fillin ; redraw the missing rectangle (if within clip region) Pull "cy0" CMP cy0,y0 LDRLT R14,dy ADDLT cy1,y0,R14 BLLT scroll_fillin Pull "cx0,cy0,cx1,cy1" ; Debug ,"calc_w_iconposn (v-scrollbar)",R3,x0,y0,x1,y1 SUB R0,y1,y0 LDR R14,dy CMP R0,R14 BLE novscroll LDR R1,up_height LDR R14,down_height ADD R1,R1,R14 | MOV R0,#iconposn_vscroll BL calc_w_iconposn ; get the bounds of the scroll region (including the up/down arrows) ] Push "y0,y1" [ ChildWindows CMP R1,R0 ; if scrollbar gets too small, we must squash the arrows to fit BLE vscrollfits MOV R0,R0,LSR #1 ; divide equally between up/down arrows LDR R1,dy_1 BIC R0,R0,R1 ; round to next pixel boundary ADD y0,y0,R0 MOV R2,#windowicon_up ; plot the up arrow (if possible) LDR R0,up_height BL plot_windowglyph_vscaled LDREQ R1,=sysicon ; if not then use the normal text glyph! ADREQ R2,uparrowicon BLEQ drawicon_system ; this should at least centre and clip the arrow LDR R14,dy ADD y1,y0,R14 ; overlap by one pixel LDR y0,[SP],#8 ; correct stack at the same time MOV R2,#windowicon_down LDR R0,down_height BL plot_windowglyph_vscaled ; plot the down arrow (if possible) LDREQ R1,=sysicon ADREQ R2,downarrowicon BLEQ drawicon_system ; otherwise use VDU 5 B novscroll vscrollfits ] LDR R1,dy LDR R14,up_height ADD R14,R14,R1 SUB y0,y1,R14 ; MOV R2,#windowicon_up BL plot_windowglyph LDREQ R1,=sysicon ; if not then use the normal text glyph! ADREQ R2,uparrowicon BLEQ drawicon_system ; Pull "y0,y1" LDR R1,dy LDR R14,down_height ; down height +1 ADD R14,R14,R1 ADD y1,y0,R14 ; MOV R2,#windowicon_down BL plot_windowglyph ; plot the down arrow (if possible) LDREQ R1,=sysicon ADREQ R2,downarrowicon BLEQ drawicon_system ; otherwise use VDU 5 ; Push "R3-R4" MOVS R0,R4 LDRNE R14,[R0,#tool_vwelltcap] TEQNE R14,#0 ; plot using sprites? BL getvscrollcoords [ TrueIcon3 :LAND: colourmoreborder BLNE forcetint_off ] BLNE dofunkyvscroll ; yes, so plot it ... BNE %FT01 ; and then ignore the rest of the code ; Push "cx0,cy0,cx1,cy1" [ TrueIcon3 LDR R0, truescoutcolour | LDRB R0,[handle,#w_scouter] ] BL window_bg MOV R1,#if_filled:OR:if_border BL drawicon_system Pull "x0,y0,x1,y1" ; [ TrueIcon3 LDR R0, truescincolour | LDRB R0,[handle,#w_scinner] ] BL window_bg MOV R1,#if_filled:OR:if_border BL drawicon_system 01 Pull "R3-R4" novscroll [ TrueIcon3 LDR R0, titlecolour | LDRB R0,titlecolour ] BL window_bg ; MOV R0,#iconposn_resize BL calc_w_iconposn ; get the bounding box no matter what - its quite quick! ; TST R3,#wf_icon6 ; resize box? BEQ %FT00 ; [ TrueIcon3 :LAND: colourmoreborder BL forcetint_on ] MOV R2,#windowicon_resize BL plot_windowglyph LDREQ R1,=sysicon ADREQ R2,sizeicon BLEQ drawicon_system ; plot using a VDU 5 glyph B %FT01 00 TST R3,#wf_icon5 ; if both scroll bars, draw blank TSTNE R3,#wf_icon7 BEQ %FT01 ; [ TrueIcon3 :LAND: colourmoreborder BL forcetint_on ] TEQ R4,#0 LDRNE R14,tool_list LDRNE R2,[R14,#tool_blank] ; blank splot type tool icon thingi? TEQNE R2,#0 BLNE draw_spriteglyph ; plot the sprite if thats present LDREQ R1,=sysicon ADREQ R2,blankicon BLEQ drawicon_system 01 TST R3,#wf_icon7 BEQ nohscroll ; [ ChildWindows Push "cx0,cy0,cx1,cy1" MOV R0,#iconposn_hscroll BL calc_w_iconposn2 ; x0..y1 = actual bounds, cx0..cy1 = 'normal' bounds LDR R14,dx SUB R0,cx1,R14 CMP x0,R0 ; force within the 'normal' box MOVGT x0,R0 ADD R0,cx0,R14 CMP x1,R0 MOVLT x1,R0 ADD R0,x0,R14 CMP x1,R0 MOVLT x1,R0 Push "cx1" CMP cx0,x0 LDRLT R14,dx ADDLT cx1,x0,R14 BLLT scroll_fillin ; redraw the missing rectangle (if within clip region) Pull "cx1" CMP x1,cx1 LDRLT R14,dx SUBLT cx0,x1,R14 BLLT scroll_fillin Pull "cx0,cy0,cx1,cy1" SUB R0,x1,x0 LDR R14,dx CMP R0,R14 BLE nohscroll LDR R1,left_width LDR R14,right_width ADD R1,R1,R14 | MOV R0,#iconposn_hscroll BL calc_w_iconposn ; get the bounds ] Push "x0,x1" [ ChildWindows CMP R1,R0 ; if scrollbar gets too small, we must squash the arrows to fit BLE hscrollfits MOV R0,R0,LSR #1 ; divide equally between up/down arrows LDR R1,dx_1 BIC R0,R0,R1 ; round to next pixel boundary ADD x1,x0,R0 LDR R14,dx ADD x1,x1,R14 ; overlap by one pixel MOV R2,#windowicon_left ; plot the left arrow (if possible) LDR R0,left_width BL plot_windowglyph_hscaled LDREQ R1,=sysicon ; if not then use the normal text glyph! ADREQ R2,leftarrowicon BLEQ drawicon_system ; this should at least centre and clip the arrow LDR R14,dx SUB x0,x1,R14 ; overlap by one pixel Pull "R2,x1" ; retrieve x1 and correct stack MOV R2,#windowicon_right LDR R0,right_width BL plot_windowglyph_hscaled ; plot the right arrow (if possible) LDREQ R1,=sysicon ADREQ R2,rightarrowicon BLEQ drawicon_system ; otherwise use VDU 5 B nohscroll hscrollfits ] LDR R1,dx LDR R14,left_width ADD R14,R14,R1 ADD x1,x0,R14 ; MOV R2,#windowicon_left BL plot_windowglyph ; plot sprite if possible LDREQ R1,=sysicon ADREQ R2,leftarrowicon BLEQ drawicon_system ; otherwise, use VDU 5 glyphs ; Pull "x0,x1" LDR R1,dx LDR R14,right_width ADD R14,R14,R1 SUB x0,x1,R14 ; MOV R2,#windowicon_right BL plot_windowglyph ; plot sprite if possible LDREQ R1,=sysicon ADREQ R2,rightarrowicon BLEQ drawicon_system ; MOVS R0,R4 LDRNE R14,[R0,#tool_hwelllcap] TEQNE R14,#0 ; plot using sprites? BL gethscrollcoords ; get the bounds of the two areas - including blobs etc... [ TrueIcon3 :LAND: colourmoreborder BLNE forcetint_off ] BLNE dofunkyhscroll ; and then plot using sprites BNE nohscroll ; Push "cx0,cy0,cx1,cy1" [ TrueIcon3 LDR R0, truescoutcolour | LDRB R0,[handle,#w_scouter] ] BL window_bg MOV R1,#if_filled:OR:if_border BL drawicon_system Pull "x0,y0,x1,y1" ; [ TrueIcon3 LDR R0, truescincolour | LDRB R0,[handle,#w_scinner] ] BL window_bg MOV R1,#if_filled:OR:if_border BL drawicon_system nohscroll [ Twitter BL checktwitter BLNE antitwitter ] [ TrueIcon3 [ colourmoreborder BL forcetint_off ] MOV R14, #0 STRB R14, tinted_window ] LDR R14,ThreeDFlags TST R14,#ThreeDFlags_WindowOutlineOver BLNE drawwindowoutline doneborder [ Autoscr LDR R14, dragflags TST R14, #dragf_clip ; clipped dragboxes must only be redrawn within their own window's work area BLEQ forcedrag_on ; put back drag rectangle if nec. | BL forcedrag_on ; put back drag rectangle if nec. ] Pull "R1" endredrawoutlp SetRectPtrs LDR R1,[rectlinks,R1] CMP R1,#nullptr BNE redrawoutlp Pull "userblk,handle" ; ; mark border valid ; MOV R0,#windowrects MOV R1,#borderrects ADD R14,handle,#w_wax0 LDMIA R14,{cx0,cy0,cx1,cy1} BL subrect MOV R0,#invalidrects MOV R1,#borderrects BL subrects MOV R0,#borderrects BL loserects ; ; now clip window list to the window's work area ; ADD R14,handle,#w_wax0 LDMIA R14,{cx0,cy0,cx1,cy1} MOV R0,#windowrects MOV R1,R0 BL intrect ; ; subtract outer rectangles of all child windows ; (note that this will often not do anything, since child windows are normally redrawn first) ; NB: If we're doing a braindead panic redraw, DON'T clip out the children - we could run out of rectangles! ; [ ChildWindows LDR R14,BPR_indication CMP R14,#BPR_continuelevel MOVLO R1,#0 BLLO subtract_children ; remove child windows from the list ] ; ; set ecf origin to window's work area origin ; LDR R14,[handle,#w_scx] SUB R0,cx0,R14 LDR R14,[handle,#w_scy] SUB R1,cy1,R14 SWI XOS_SetECFOrigin ; ; set up return data by exiting via Get_Rectangle ; [ Twitter BL checktwitter MOV r14, #getrect_redrawing:OR:getrect_firstrect ORRNE r14, r14, #getrect_twitter | MOV R14,#getrect_redrawing:OR:getrect_firstrect ] STR R14,getrectflags ; Pull LR B int_get_rectangle ; ; definitions of the various bits and pieces (icons) ; sysicon * if_text:OR:if_filled:OR:if_border:OR:if_hcentred sysicon2 * if_sprite:OR:if_filled:OR:if_border:OR:if_hcentred [ ChildWindows sizeicon DCD &0D83 | backicon DCD &0D85 ; moved to the start quiticon DCD &0D84 sizeicon DCD &0D83 toggleicon1 DCD &0D81 toggleicon2 DCD &0D82 ] uparrowicon DCD &0D8B downarrowicon DCD &0D8A leftarrowicon DCD &0D88 rightarrowicon DCD &0D89 [ IconiseButton iconiseicon DCD &0D98 ] blankicon DCD &0D ALIGN LTORG ;------------------------------------------------------------------------------- drawwindowoutline Entry "r0-r9" ADD R0,handle,#w_x0 LDMIA R0,{x0,y0,x1,y1} ; ; draw border round work area (unless w_tfcol = 255) ; [ ChildWindows LDRB R14,[handle,#w_tfcol] TEQ R14,#255 BNE have_thin_outline [ TrueIcon3 LDR R0, truetitlefg | MOV R0,#7 ; set black border in case toolsprites need it... ] BL window_fg B no_thin_outline have_thin_outline ] ; LDR R14,dx ; ADD x0,x0,R14 ; SUB x1,x1,R14 ; LDR R14,dy ; ADD y0,y0,R14 ; SUB y1,y1,R14 [ TrueIcon3 LDR R0, truetitlefg ; set title foreground colour CMP R0, #0 ; is foreground colour black? LDREQ R0, truewindowoutlinecolour ; if so, get window outline colour | LDRB R0,[handle,#w_tfcol] ; set title foreground colour ] BL window_fg BL hollowrectangle [ ChildWindows no_thin_outline ] EXIT ;------------------------------------------------------------------------------- [ TrueIcon3 ; ; Ensures window tool tinting is on, if appropriate for this window ; forcetint_on EntryS "R0,R2" LDR R2, tool_list LDR R2, [R2] TEQ R2, #0 ; don't bother if there aren't any tools EXITS EQ LDRB R0, tinted_window LDRB R14, tinted_tool TEQ R0, #0 TEQNE R0, R14 STRNEB R0, tinted_tool BLNE recache_tools_trans ; uses R2 as set up above (-> first sprite) EXITS ; must preserve flags ; ; Ensures window tool tinting is off ; forcetint_off EntryS "R2" LDR R2, tool_list LDR R2, [R2] TEQ R2, #0 ; don't bother if there aren't any tools EXITS EQ LDRB R14, tinted_tool TEQ R14, #0 MOVNE R14, #0 STRNEB R14, tinted_tool BLNE recache_tools_trans ; uses R2 as set up above (-> first sprite) EXITS ; must preserve flags ] ;.............................................................................. ; In cx0,cy0,cx1,cy1 = box to fill in ; [clipx0..y1] = current graphics window ; Out solidrectangle drawn if box is visible [ ChildWindows scroll_fillin ROUT Push "R0,R1,cx0,cy0,cx1,cy1,x0,y0,x1,y1,LR" CMP cx0,cx1 CMPLT cy0,cy1 BGE %FT90 Push "cx0,cy0,cx1,cy1" Pull "x0,y0,x1,y1" ADR R14,clipx0 ; used by drawicon LDMIA R14,{cx0,cy0,cx1,cy1} CMP x0,cx1 CMPLT y0,cy1 CMPLT cx0,x1 CMPLT cy0,y1 BGE %FT90 BL hollowrectangle LDR R14,dx ADD x0,x0,R14 SUB x1,x1,R14 LDR R14,dy ADD y0,y0,R14 SUB y1,y1,R14 CMP x0,x1 CMPLT y0,y1 BLLT solidrectangle 90 Pull "R0,R1,cx0,cy0,cx1,cy1,x0,y0,x1,y1,PC" ] ;;---------------------------------------------------------------------------- ;; Routines for working out scroll bar indicators ;;---------------------------------------------------------------------------- ;----------------------------------------------------------------------------- ; Get coords for dragging scroll bars ;----------------------------------------------------------------------------- draghscrollcoords Push "R0,LR" ; BL gethscrollcoords LDRB R14,scroll_sidemargin ADD y0,y0,R14 SUB y1,y1,R14 LDRB R14,scroll_endmargin ADD x0,x0,R14 SUB x1,x1,R14 ; SUBS R14,x1,cx1 ADDLT cx0,cx0,R14 ADDLT cx1,cx1,R14 SUBS R14,x0,cx0 ADDGT cx0,cx0,R14 ADDGT cx1,cx1,R14 ; ensure box is within parent SUBS R14,x1,cx1 SUBLT x1,x1,R14 ; give up! ; Pull "R0,PC" dragvscrollcoords Push "R0,LR" ; BL getvscrollcoords LDRB R14,scroll_sidemargin ADD x0,x0,R14 SUB x1,x1,R14 LDRB R14,scroll_endmargin ADD y0,y0,R14 SUB y1,y1,R14 ; SUBS R14,y1,cy1 ADDLT cy0,cy0,R14 ADDLT cy1,cy1,R14 SUBS R14,y0,cy0 ADDGT cy0,cy0,R14 ADDGT cy1,cy1,R14 ; ensure box is within parent SUBS R14,y1,cy1 SUBLT y1,y1,R14 ; give up! ; Pull "R0,PC" draghvscrollcoords Push "LR" BL draghscrollcoords ; get x0,x1,cx0,cx1 Push "x0,x1,cx0,cx1" BL dragvscrollcoords ; get y0,y1,cy0,cy1 Pull "x0,x1,cx0,cx1,PC" ;----------------------------------------------------------------------------- ; Get coords of inner and outer boxes (for Redraw_Window) ; Exit: x0,y0,x1,y1 = outer bounding box ; cx0,cy0,cx1,cy1 = inner scroll bar indicator ;----------------------------------------------------------------------------- ; Two sets of routines; cf getbnewscy etc. RISC OS 3.1 had the first ; routine here and there. Scroll bars dragged neatly, but it was impossible ; to drag to the bottom (or right) of a very wide window (because the ; scroll bar was over large). In RISC OS 3.5, getnewscy was modified to ; fix this, but there was the unfortunate side-effect that the slider ; didn't follow the pointer near the bottom or right of a large window. ; Indeed, just grabbing the slider at the bottom of a tall window would ; make the window jump two or three page fulls. The new routine here ; takes into account the excess height of the slider when determining ; its display position. [ false getvscrollcoords EntryS "R0,R1" ; MOV R0,#5 ; v_scroll BL calc_w_iconposn LDR cy0,[handle,#w_way0] LDR cy1,[handle,#w_way1] SUB R1,cy1,cy0 ; get work area size LDR R14,down_height ADD y0,y0,R14 LDR R14,up_height SUB y1,y1,R14 ; LDR R0,[handle,#w_scy] LDR R14,[handle,#w_wey1] SUB R0,R14,R0 ; +ve offset ; Push "R0,R1" BL calc_scrolly ; R0 <-- FNscy(R0) SUB cy1,y1,R0 ; upper coordinate LDR R14,dy_1 ; R14 <- dy-1 BIC cy1,cy1,R14 Pull "R0,R1" ; ADD R0,R0,R1 ; move to lower end BL calc_scrolly SUB cy0,y1,R0 ; lower coordinate ; LDRB R1,scroll_minlength ; min size of v scroll bar [ hvblip LDR R14,vscroll_blipheight ADD R1,R1,R14 LDR R14,dy SUB R1,R1,R14 ; account for the blip ] SUB R14,cy1,cy0 CMP R14,R1 ; minimum size! SUBLT cy0,cy1,R1 LDRB R1,scroll_endmargin SUB R14,cy0,y0 SUBS R14,R14,R1 ; minimum y coord SUBLT cy0,cy0,R14 SUBLT cy1,cy1,R14 SUB R14,y1,cy1 SUBS R14,R14,R1 ; maximum y coord ADDLT cy1,cy1,R14 ; LDRB R1,scroll_sidemargin ADD cx0,x0,R1 SUB cx1,x1,R1 ; EXITS | getvscrollcoords EntryS "R0,R1" ; MOV R0,#iconposn_vscroll BL calc_w_iconposn ; y0,y1 = scroll bar (inc arrows) LDR cy0,[handle,#w_way0] LDR cy1,[handle,#w_way1] SUB R1,cy1,cy0 ; R1 = work area height LDR R14,down_height ADD y0,y0,R14 LDR R14,up_height SUB y1,y1,R14 ; y0,y1 = scroll bar well MOV cx0,R1 LDR R14,[handle,#w_wey0] LDR R0,[handle,#w_wey1] ; R0 = well height * work area SUB cx1,R0,R14 ; --------- SUB R0,y1,y0 ; extent LDRB R14,scroll_endmargin SUB R0,R0,R14,LSL #1 LDRB R1,scroll_minlength [ hvblip LDR R14,vscroll_blipheight ADD R1,R1,R14 LDR R14,dy SUB R1,R1,R14 ; account for the blip ] [ ChildWindows CMP R1,R0 BLT %FT01 ; slider won't fit! LDRB R14,scroll_endmargin SUB cy1,y1,R14 ADD cy0,y0,R14 ; first try to fill available well with slider CMP cy1,cy0 [ RO4 :LOR: true ADDLT cy1,y0,y1 ; then, if negative, put in a zero-height slider in centre of well MOVLT cy1,cy1,LSR #1 MOVLT cy0,cy1 | ADDLO cy1,y0,y1 ; then, if negative, put in a zero-height slider in centre of well MOVLO cy1,cy1,LSR #1 MOVLO cy0,cy1 ] B %FT02 01 ] BL muldivR0 ; = sausage height Push "R0,R1,y0" SUBS R14,R1,R0 ; Fakery to allow for large slider ADDGT y0,y0,R14 LDR R0,[handle,#w_scy] LDR R14,[handle,#w_wey1] SUB R0,R14,R0 ; +ve offset BL calc_scrolly ; R0 = slider position SUB cy1,y1,R0 ; cy1 = upper coordinate Pull "R0,R1,y0" CMP R0,R1 MOVLT R0,R1 SUB cy0,cy1,R0 ; cy0 = lower slider coordinate LDR R14,dy_1 ; R14 = dy-1 BIC cy1,cy1,R14 ; round nicely BIC cy0,cy0,R14 LDRB R1,scroll_endmargin SUB R14,cy0,y0 SUBS R14,R14,R1 ; minimum y coord SUBLT cy0,cy0,R14 SUBLT cy1,cy1,R14 SUB R14,y1,cy1 SUBS R14,R14,R1 ; maximum y coord ADDLT cy1,cy1,R14 ; 02 LDRB R1,scroll_sidemargin ADD cx0,x0,R1 SUB cx1,x1,R1 ; EXITS ] [ false gethscrollcoords EntryS "R0,R1" ; MOV R0,#7 ; h_scroll BL calc_w_iconposn LDR cx0,[handle,#w_wax0] LDR cx1,[handle,#w_wax1] SUB R1,cx1,cx0 ; get work area size LDR R14,left_width ADD x0,x0,R14 LDR R14,right_width SUB x1,x1,R14 ; LDR R0,[handle,#w_scx] LDR R14,[handle,#w_wex0] SUB R0,R0,R14 ; Push "R0,R1" BL calc_scrollx ; R0 <-- FNscy(R0) ADD cx0,x0,R0 ; left-hand coordinate LDR R14,dx_1 ; R14 <- dx-1 BIC cx0,cx0,R14 Pull "R0,R1" ; ADD R0,R0,R1 BL calc_scrollx ADD cx1,x0,R0 ; right-hand coordinate ; LDRB R1,scroll_minlength [ hvblip LDR R14,hscroll_blipwidth ADD R1,R1,R14 LDR R14,dx SUB R1,R1,R14 ; account for the blip ] SUB R14,cx1,cx0 CMP R14,R1 ; minimum size! ADDLT cx1,cx0,R1 LDRB R1,scroll_endmargin SUB R14,x1,cx1 SUBS R14,R14,R1 ; maximum x coord ADDLT cx0,cx0,R14 ADDLT cx1,cx1,R14 SUB R14,cx0,x0 SUBS R14,R14,R1 ; minimum x coord SUBLT cx0,cx0,R14 ; LDRB R1,scroll_sidemargin ADD cy0,y0,R1 SUB cy1,y1,R1 ; EXITS | gethscrollcoords EntryS "R0,R1" ; MOV R0,#7 ; h_scroll BL calc_w_iconposn ; x0,x1 = scroll bar (inc arrows) LDR cx0,[handle,#w_wax0] LDR cx1,[handle,#w_wax1] SUB R1,cx1,cx0 ; R1 = work area width LDR R14,left_width ADD x0,x0,R14 LDR R14,right_width SUB x1,x1,R14 ; x0,x1 = scroll bar well MOV cx0,R1 LDR R14,[handle,#w_wex0] LDR R0,[handle,#w_wex1] ; R0 = well width * work area SUB cx1,R0,R14 ; --------- SUB R0,x1,x0 ; extent LDRB R14,scroll_endmargin SUB R0,R0,R14,LSL #1 LDRB R1,scroll_minlength [ hvblip LDR R14,hscroll_blipwidth ADD R1,R1,R14 LDR R14,dx SUB R1,R1,R14 ; account for the blip ] [ ChildWindows CMP R1,R0 BLT %FT01 ; slider won't fit! LDRB R14,scroll_endmargin SUB cx1,x1,R14 ADD cx0,x0,R14 ; first try to fill available well with slider CMP cx1,cx0 [ RO4 :LOR: true ADDLT cx1,x0,x1 ; then, if negative, put in a zero-height slider in centre of well MOVLT cx1,cx1,LSR #1 MOVLT cx0,cx1 | ADDLO cx1,x0,x1 ; then, if negative, put in a zero-height slider in centre of well MOVLO cx1,cx1,LSR #1 MOVLO cx0,cx1 ] B %FT02 01 ] BL muldivR0 ; = slider width Push "R0,R1,x1" SUBS R14,R1,R0 ; Fakery to allow for large slider SUBGT x1,x1,R14 LDR R0,[handle,#w_scx] LDR R14,[handle,#w_wex0] SUB R0,R0,R14 BL calc_scrollx ; R0 = slider position ADD cx0,x0,R0 ; cx0 = left-hand coordinate Pull "R0,R1,x1" CMP R0,R1 MOVLT R0,R1 ADD cx1,cx0,R0 ; cx1 = right-hand slider coordinate LDR R14,dx_1 ; R14 = dx-1 BIC cx0,cx0,R14 ; round nicely BIC cx1,cx1,R14 LDRB R1,scroll_endmargin SUB R14,x1,cx1 SUBS R14,R14,R1 ; maximum x coord ADDLT cx0,cx0,R14 ADDLT cx1,cx1,R14 SUB R14,cx0,x0 SUBS R14,R14,R1 ; minimum x coord SUBLT cx0,cx0,R14 ; 02 LDRB R1,scroll_sidemargin ADD cy0,y0,R1 SUB cy1,y1,R1 ; EXITS ] ;--------------------------------------------------------------------------- ; routine to work out the appropriate coordinate offset for a scroll bar ; Entry: R0 = 'scroll' offset from top-left of area ; x0,y0,x1,y1 = outer scroll box ; Exit : R0 = offset from outer box to scroll bar indicator ;--------------------------------------------------------------------------- calc_scrollx Push "cx0,cx1,LR" ADD R1,handle,#w_x0-w_x0 MOV cx0,x0 MOV cx1,x1 B calc_scroll calc_scrolly Push "cx0,cx1,LR" MOV cx0,y0 MOV cx1,y1 ADD R1,handle,#w_y0-w_x0 calc_scroll LDRB R14,scroll_endmargin SUB cx0,cx1,cx0 SUB cx0,cx0,R14,LSL #1 ; allow for gaps LDR cx1,[R1,#w_wex1] LDR R14,[R1,#w_wex0] SUB cx1,cx1,R14 ; size of work area extent BL muldivR0 ; R0 <- R0 * cx0 / cx1 LDRB R14,scroll_endmargin ADD R0,R0,R14 ; allow gap at end ; Pull "cx0,cx1,PC" ;----------------------------------------------------------------------------- ; Routines to work out new position of scroll bar after dragging ;----------------------------------------------------------------------------- ; ; Entry: cx0,cy0,cx1,cy1 = posn of drag box ; Exit: x0 = new scroll x coord ; getnewscx [ false Push "R0,R1,y0,x1,y1,LR" ; MOV R0,#7 ; h_scroll BL calc_w_iconposn SUB R0,cx0,x0 ; offset of box LDRB R14,scroll_mxborder SUBS R0,R0,R14 ; allow for gap at end MOVLT R0,#0 ; result is always positive ; Push "cx0,cx1" LDR cx0,[handle,#w_wex1] LDR R14,[handle,#w_wex0] SUB cx0,cx0,R14 SUB cx1,x1,x0 ; get size of outer bit LDRB R14,scroll_mxborder SUB cx1,cx1,R14,LSL #1 ; allow for arrow boxes BL muldivR0 ; R0 <- R0 * cx0 / cx1 Pull "cx0,cx1" ; LDR R14,[handle,#w_wex0] ADD x0,R14,R0 ; result in x0 ; Pull "R0,R1,y0,x1,y1,PC" | Push "R0,R1,y0,x1,y1,LR" ; MOV R0,#7 ; h_scroll BL calc_w_iconposn SUB R0,cx0,x0 ; offset of box LDRB R14,scroll_mxborder SUBS R0,R0,R14 ; allow for gap at end MOVLT R0,#0 ; result is always positive ; Push "cx0,cx1" Push "cy0,cy1" LDR cx0,[handle,#w_wex1] LDR R14,[handle,#w_wex0] LDR cy0,[handle,#w_wax1] LDR cy1,[handle,#w_wax0] SUB cy0,cy0,cy1 ; width on screen SUB cx0,cx0,R14 SUB cx0,cx0,cy0 ; WE-amount viewable ADD R14,SP,#8 ; need cx1 cx0 LDMIA R14,{cy0,cy1} SUB cx1,x1,x0 ; get size of outer bit SUB cx1,cx1,cy1 ADD cx1,cx1,cy0 Pull "cy0,cy1" CMP R0,cx1 MOVGT R0,cx1 LDRB R14,scroll_mxborder SUB cx1,cx1,R14,LSL #1 ; allow for arrow boxes BL muldivR0 ; R0 <- R0 * cx0 / cx1 Pull "cx0,cx1" ; LDR R14,[handle,#w_wex0] ADD x0,R14,R0 ; result in x0 ; Pull "R0,R1,y0,x1,y1,PC" ] getnewscy ; these two alternatives use the same algebraic formula to determine the ; corresponding work area coordinate for a scrollbar value. The former ; makes the assumption that 'sausage height = screen height / work area ; extent'. Although algebraically correct, due to integer arithmetic, it ; is slightly different in practice for large extents. [ false Push "R0,R1,x0,x1,y1,LR" ; MOV R0,#5 ; v_scroll BL calc_w_iconposn SUB R0,y1,cy1 ; offset of box LDRB R14,scroll_myborder SUBS R0,R0,R14 ; allow for gap at end MOVLT R0,#0 ; result is always positive ; Push "cx0,cx1" LDR cx0,[handle,#w_wey1] LDR R14,[handle,#w_wey0] SUB cx0,cx0,R14 SUB cx1,y1,y0 ; get size of outer box LDRB R14,scroll_myborder SUB cx1,cx1,R14,LSL #1 ; allow for arrow boxes BL muldivR0 ; R0 <- R0 * cx0 / cx1 Pull "cx0,cx1" ; LDR R14,[handle,#w_wey1] SUB y0,R14,R0 ; result in y0 ; Pull "R0,R1,x0,x1,y1,PC" | Push "R0,R1,x0,x1,y1,LR" ; MOV R0,#5 ; v_scroll BL calc_w_iconposn SUB R0,y1,cy1 ; offset of box LDRB R14,scroll_myborder SUBS R0,R0,R14 ; allow for gap at end MOVLT R0,#0 ; result is always positive ; Push "cx0,cx1" Push "cy0,cy1" LDR cx0,[handle,#w_wey1] LDR R14,[handle,#w_wey0] LDR cy0,[handle,#w_way1] LDR cy1,[handle,#w_way0] SUB cy0,cy0,cy1 ; height on screen SUB cx0,cx0,R14 SUB cx0,cx0,cy0 ; work area extent - ammount viewable Pull "cy0,cy1" SUB cx1,y1,y0 ; get size of outer box SUB cx1,cx1,cy1 ADD cx1,cx1,cy0 ; adjust for size of 'sausage' CMP R0,cx1 MOVGT R0,cx1 LDRB R14,scroll_myborder SUB cx1,cx1,R14,LSL #1 ; allow for arrow boxes BL muldivR0 ; R0 <- R0 * cx0 / cx1 Pull "cx0,cx1" ; LDR R14,[handle,#w_wey1] SUB y0,R14,R0 ; result in y0 ; Pull "R0,R1,x0,x1,y1,PC" ] ; ; muldivR0 ; Entry: R0 = input value ; cx0,cx1 = multiplier / divisor ; Exit: R0 = R0 * cx0 / cx1 ; (overflow avoided by shifting down cx0,cx1 as necessary) ; muldivR0 Push "R1,cx0,cx1,x0,LR" ; MOV R1,#0 ; use binary chop to count 0 bits ; MOV x0,cx0 BL count0bits MOV x0,R0 BL count0bits ; R1 = total 0 bits at top of R0,cx0 ; RSBS R14,R1,#34 ; if less than 34, do some shifting MOVGT cx0,cx0,ASR R14 MOVGT cx1,cx1,ASR R14 TEQ cx1,#0 MOVEQ cx1,#1 ; avoid 'division by zero' ; MUL x0,R0,cx0 ADD x0,x0,cx1,ASR #1 ; round to nearest DivRem R0,x0,cx1, R14 ; Pull "R1,cx0,cx1,x0,PC" count0bits Push "LR" ; MOVS R14,x0,LSR #32-16 ; see if top 16 bits are zero ADDEQ R1,R1,#16 MOVEQ x0,x0,LSL #16 ; MOVS R14,x0,LSR #32-8 ; see if top 8 bits are zero ADDEQ R1,R1,#8 MOVEQ x0,x0,LSL #8 ; MOVS R14,x0,LSR #32-4 ; see if top 4 bits are zero ADDEQ R1,R1,#4 MOVEQ x0,x0,LSL #4 ; MOVS R14,x0,LSR #32-2 ; see if top 2 bits are zero ADDEQ R1,R1,#2 MOVEQ x0,x0,LSL #2 ; Pull "PC" ;;-------------------------------------------------------------------------- ;; Update_Window - application calls this when it wants to draw in a window ;; N.B. - in this case, the screen is OK before the call, so can be used. ;;-------------------------------------------------------------------------- SWIWimp_UpdateWindow MyEntry "UpdateWindow" ; LDR handle,[userblk] BL checkhandle_owner BVS ExitWimp ADD R14,userblk,#u_wax0 LDMIA R14,{x0,y0,x1,y1} MOV R0,#getrect_firstrect:OR:getrect_updating BL int_update_window2 B Exit_via_get_rectangle ;----------------------------------------------------------------------------- ; Find visible list of window's work area ; Entry: x0,y0,x1,y1 = area of window which is changing ; Exit : windowrects list set up - Get_Rectangle NOT CALLED YET!!! ;----------------------------------------------------------------------------- int_update_window [ Twitter Push "lr" BL checktwitter Pull "lr" MOV r0, #getrect_firstrect:OR:getrect_updating ORRNE r0, r0, #getrect_twitter | MOV R0,#getrect_firstrect:OR:getrect_updating ] int_update_window2 STR R0,getrectflags int_update_window3 Push "LR" Debug opn,"int_update_window",handle,#getrectflags [ ChildWindows BL int_flush_opens ] Rel R14,handle STR R14,redrawhandle LDR R14,[handle,#w_taskhandle] Task R14,,"UpdateW" ; page in the window owner [ Twitter BL checktwitter SUBNE y0, y0, #2 ADDNE y1, y1, #2 ] BL int_visibleinner_x0y0x1y1 [ TrueIcon3 ; set up true colours BL setwindowcolours ] Pull "PC" [ ThreeDPatch int_visibleinner_ignore3Dboder_x0y0x1y1 Push "x0,y0,x1,y1,LR" ; BL CheckIfWindowRequires3DBorders BNE %FT01 BL visibleinnerportion_3D ; this subtracts the child windows B %FT02 01 BL visibleinnerportion ; this subtracts the child windows 02 MOV R0,#windowrects ; only the VALID bits MOV R1,#invalidrects BL subrects ; ADD R14,handle,#w_wax0 LDMIA R14!,{x0,y0,x1,y1} LDMIA R14,{cx1,cy1} SUB cx1,x0,cx1 ; coords of top-left SUB cy1,y1,cy1 MOV R0,cx1 MOV R1,cy1 SWI XOS_SetECFOrigin ; for Wimp_UpdateWindow ; Pull "x0,y0,x1,y1" ADD cx0,x0,cx1 ADD cy0,y0,cy1 ADD cx1,x1,cx1 ADD cy1,y1,cy1 ; MOV R0,#windowrects MOV R1,R0 BL intrect ; Pull "PC" ] int_visibleinner_x0y0x1y1 Push "x0,y0,x1,y1,LR" ; BL visibleinnerportion ; this subtracts the child windows MOV R0,#windowrects ; only the VALID bits MOV R1,#invalidrects BL subrects ; ADD R14,handle,#w_wax0 LDMIA R14!,{x0,y0,x1,y1} LDMIA R14,{cx1,cy1} SUB cx1,x0,cx1 ; coords of top-left SUB cy1,y1,cy1 MOV R0,cx1 MOV R1,cy1 SWI XOS_SetECFOrigin ; for Wimp_UpdateWindow ; Pull "x0,y0,x1,y1" ADD cx0,x0,cx1 ADD cy0,y0,cy1 ADD cx1,x1,cx1 ADD cy1,y1,cy1 ; MOV R0,#windowrects MOV R1,R0 BL intrect ; Pull "PC" ;;--------------------------------------------------------------------------- ;; Get_Rectangle - return next rectangle from windowrects list ;;--------------------------------------------------------------------------- SWIWimp_GetRectangle MyEntry "GetRectangle" [ ChildWindows BL int_flush_opens ; it's barmy if there are any, but we want the correct error message ] LDR handle,[userblk] LDR R1,redrawhandle TEQ handle,R1 BNE errgetrectangle BL checkhandle_owner ; Exit_via_get_rectangle BLVC int_get_rectangle ; on exit x0,y0,x1,y1 = clip window BVS ExitWimp ; ExitGetRectangle Push R0 ADD R14,handle,#w_wax0 LDMIA R14,{R0-R5} ; get work area x0,y0,x1,y1,scx,scy ADD R14,userblk,#4 ; skip handle STMIA R14,{R0-R5,x0,y0,x1,y1} ; plus clip window coords Pull R0 B ExitWimp errgetrectangle MyXError WimpGetRect B ExitWimp MakeErrorBlock WimpGetRect ; ; sensitive routines should set redrawhandle back to null ; checkredrawhandle Push "LR" ; MOV R14,#nullptr STR R14,redrawhandle ; Pull "PC" ;----------------------------------------------------------------------------- ; internal entry point (NOT called by int_redraw_window) ; this routine does not put any data into [userblk] ; - that is only done on exit from the SWI !!! ;----------------------------------------------------------------------------- int_get_rectangle Push LR ; Debug opn, "int_get_rectangle", handle, #getrectflags ; SWI XOS_WriteI+5 ; just in case ; ; draw user icons for previous rectangle (if redrawing) ; ; [ Twitter LDR r14, getrectflags TST r14, #getrect_firstrect BNE %FT10 TST R14, #getrect_noicons BLEQ drawusericons ; draw icons if wanted (for previous) Pull "PC",VS LDR R14,getrectflags TST R14,#getrect_firstrect:OR:getrect_noicons BNE %FT20 ADR R14,clipx0 LDMIA R14,{x0,y0,x1,y1} CallFilter posticonfilter LDR r14, getrectflags TST r14, #getrect_twitter BLNE antitwitter LDRNE r14, getrectflags TST r14, #getrect_noicons BLEQ forcecaret Pull "PC",VS 10 | LDR R14,getrectflags TST R14,#getrect_firstrect:OR:getrect_noicons BNE %FT20 BL drawusericons ; draw icons if wanted (for previous) Pull "PC",VS ADR R14,clipx0 LDMIA R14,{x0,y0,x1,y1} CallFilter posticonfilter BL forcecaret ; put caret back Pull "PC",VS [ ThreeDPatch :LOR: :LNOT: NCMenus ADD x0,handle,#w_wax0 LDMIA x0,{x0-y1} ] [ ThreeDPatch BL PlotWindowBorders ] [ :LNOT: NCMenus LDR r14,[handle,#w_taskhandle] CMP r14,#-1 LDREQ R14,[handle,#w_scy] SUBEQ y1,y1,R14 ; y1 = position of menu origin BLEQ redrawmenu ; draw dotted lines if nec. ] ] 20 LDR R14,getrectflags TST R14,#getrect_firstrect [ Autoscr MOVEQ R1, #0 ; invalidate current dot-dash STREQB R1, dotdash ; (user may have changed it) TST R14, #getrect_firstrect :OR: getrect_keepdragbox BIC R14, R14, #getrect_firstrect STR R14, getrectflags BNE %FT06 ; don't do it if firstrect or while plotting a clipped dragbox LDR R14, dragflags TST R14, #dragf_clip ; clipped dragboxes must only be redrawn within their own window LDRNE R14, draghandle Abs R14, R14, NE TEQNE R14, handle BLEQ forcedrag_on ; put drag box back if nec. 06 | BIC R14,R14,#getrect_firstrect STR R14,getrectflags MOVEQ R14,#0 ; invalidate current dot-dash STREQB R14,dotdash ; (user may have changed it) BLEQ forcedrag_on ; put drag box back if nec. ] Pull "PC",VS ; ; delete top rectangle from list and return it to the user ; Push "userblk,handle" SetRectPtrs ; LDR R1,[rectlinks,#windowrects] CMP R1,#nullptr [ ChocolateScreen BNE igr_nochocupdate MOV R0,#5 ; ChocolateUpdate reason code SWI XOS_ScreenMode MOV R0,#0 ; no more rectangles B getrectend igr_nochocupdate | MOVEQ R0,#0 ; no more rectangles BEQ getrectend ] ; ; delete it from the list ; LDR R14,[rectlinks,R1] STR R14,[rectlinks,#windowrects] ; link(window)=link(R1) LDR R14,[rectlinks,#freerects] STR R14,[rectlinks,R1] ; link(R1)=link(free) STR R1,[rectlinks,#freerects] ; link(free)=R1 ; getxy R1,x,y MOV R0,#-1 ; return TRUE LDR R14,getrectflags ; KJB patch - this flag is only set by the TST R14,#getrect_noicons ; caret update code. When update caret we BNE getrectend ; don't want the filter called as nothing should ; be redrawn. The caret is just EORed. ; call the rectangle processing filter LDR handle, [sp, #0*4] ; R10 = window handle (absolute) CallFilter rectanglefilter getrectend Pull "userblk,handle" ; ; set up appropriate graphics window and set appropriate colours ; CMP R0,#0 ; important to clear V MOVEQ R14,#nullptr STREQ R14,redrawhandle BLEQ defaultwindow ; restore default graphics window Pull "PC",EQ ; return FALSE ; ; if redrawing, mark rectangle valid (assume the application will redraw it!) ; Push "x0,y0,x1,y1" ; LDR R14,getrectflags TST R14,#getrect_redrawing LDMNEIA sp,{cx0,cy0,cx1,cy1} MOVNE R0,#invalidrects MOVNE R1,R0 BLNE subrect ; LDMIA sp,{x0,y0,x1,y1} BL graphicswindow [ Autoscr LDR R14, getrectflags TST R14, #getrect_keepdragbox BNE %FT06 LDR R14, dragflags TST R14, #dragf_clip ; clipped dragboxes must only be redrawn within their own window LDRNE R14, draghandle Abs R14, R14, NE TEQNE R14, handle BLEQ forcedrag_off ; get rid of drag box if nec. 06 | BL forcedrag_off ; get rid of drag box if nec. ] ; LDR R14,getrectflags TST R14,#getrect_redrawing BEQ noclrwbg ADD R14,handle,#w_wax0 ; old Wimp does this in Redraw_Window LDMIA R14,{x0,y0,x1,y1} LDRB R0,[handle,#w_wbcol] TEQ R0,#&FF ; &FF ==> don't clear background BEQ noclrwbg [ TrueIcon3 LDR R0, trueworkbg ] BL window_bg [ windowsprite LDRB R0,[handle,#w_wbcol] BL plotspritebackground | SWI XOS_WriteI+16 ] [ :LNOT: RO4 LDR R14,[handle,#w_scy] SUB y1,y1,R14 ; y1 = position of menu origin [ :LNOT: NCMenus BL redrawmenu ; draw dotted lines if nec. ] ] noclrwbg Pull "x0,y0,x1,y1" ; need these for returning to caller! ; LDR R14,getrectflags TST R14,#getrect_noicons:OR:getrect_redrawing BLEQ forcecaret ; remove caret if nec. ; LDR R14,getrectflags TST R14,#getrect_noicons BNE %FT01 CallFilter postrectfilter ; 1 [ TrueIcon3 LDR R0, trueworkfg BL window_fg LDR R0, trueworkbg BL window_bg | LDRB R0,[handle,#w_wfcol] BL window_fg LDRB R0,[handle,#w_wbcol] CMP R0,#&FF ; important to clear V MOVEQ R0,#0 ; set up a sensible colour just in case BL window_bg ] ; MOV R0,#-1 ; return TRUE Pull "PC" [ Twitter checktwitter ; In: handle = window handle ; Out: NE => twitter, EQ => don't twitter ; Entry [ ForceTwitter TEQ PC, #0 ; set NE every time!! | LDR lr, [handle, #w_flags] TST lr, #wf_autoredraw LDRNE lr, modeflags TSTNE lr, #1:SHL:8 [ TwitterOnlyMenus EXIT EQ LDR lr, [handle, #w_taskhandle] CMP lr, #-1 ; (task handle -1 => menu) ; invert the condition (so EQ if handle != -1, NE if handle = -1) TOGPSR Z_bit, lr ] ] EXIT antitwitter Entry "r0-r3" ADR r0, clipx0 LDMIA r0,{r0-r3} SUB r1,r1,#2 SUB r2,r2,r0 SUB r3,r3,r1 ADD r3,r3,#2 SWI &a38c0 CLRV EXIT ] END