; 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. ; ; > s.Wimp04 ;;--------------------------------------------------------------------------- ;; Wimp_PlotIcon ;; Entry: R1 --> block containing icon definition (userblk=R1 here) ;; [redrawhandle] --> current redraw window ;; [clipx0,y0,x1,y1] = current graphics window ;;--------------------------------------------------------------------------- SWIWimp_PlotIcon MyEntry "PlotIcon" ; [ SwitchingToSprite LDR R14, switchtospr_current ; outputting to a sprite? TEQ R14, #0 BLNE switchingtosprite_recache ; check graphics parameters are up-to-date if so ] LDR handle,redrawhandle CMP handle,#nullptr ; Not in a redraw loop. MOVEQ R14,#1 ; Use wimp sprite area STREQ R14,areaCBptr ; for sprite plotting BLEQ defaultwindow ; Set default graphics window. SWI XOS_WriteI+5 ; VDU 5 mode. BVS ExitWimp BEQ %FT01 BL checkhandle_owner ; if not in redraw, this fails BVS ExitWimp ; BL setwindowptrs 01 LDR R14,careticonaddr EOR R14,R14,userblk ; caret can't be here really! STR R14,hascaret ; LDR R1,[userblk,#i_flags] ; R1 = flag word TST R1,#is_deleted BNE ExitWimp ; ADD R2,userblk,#i_data ; R2 --> data BL seticonptrs ; NB: mustn't cause a task swap ; LDMIA userblk,{x0,y0,x1,y1} ; x0,y0,x1,y1 = bounding box ADD x0,x0,cx1 ADD y0,y0,cy1 ADD x1,x1,cx1 ADD y1,y1,cy1 ; BL drawcolouredicon ; depends on flag settings ; [ outlinefont LDR R14,systemfont TST R14,#&80000000 BEQ ExitWimp LDR userblk,[sp] LDR R1,[userblk,#i_flags] ; R1 = flag word TST R1,#if_fancyfont MOVEQ R14,#0 ; FM may fail on fancy font icons ; but not on real ones, eg. missing font ; handle. BICNE R14,R14,#&80000000 STR R14,systemfont BNE ExitWimp ; it'll probably fail again B %BT01 | B ExitWimp ] ;;--------------------------------------------------------------------------- ;; drawusericons - draw all icons in a window ;; Entry: handle --> window definition ;; [clipx0,y0,x1,y1] = current graphics clip window ;;--------------------------------------------------------------------------- drawusericons Push "LR" ; BL setwindowptrs ; sets up [careticonaddr] etc. ; Push "handle,userblk" ; ASSERT (handle<>R11) [ outlinefont LDR R11,iconbarhandle Abs R11,R11 TEQ handle,R11 LDREQB R11,iconbar_needs_rs TEQEQ R11,#1 BLEQ resizeiconbaricons ] LDR R11,[handle,#w_nicons] LDR R10,[handle,#w_icons] ; R10 --> start of icon list ADD R11,R10,R11,LSL #i_shift ; R11 --> end of list druilp CMP R10,R11 BCS doneusericons ; LDR R14,careticonaddr EOR R14,R14,R10 ; 0 ==> this icon has the caret STR R14,hascaret ; LDR R1,[R10,#i_flags] ; R1 = flag word TST R1,#is_deleted BNE %FT01 ADD R2,R10,#i_data ; R2 --> data BL seticonptrs ; NB: mustn't cause a task swap ; ADD R14,R10,#i_bbx0 ; x0,y0,x1,y1 = bounding box LDMIA R14,{x0,y0,x1,y1} ADD x0,x0,cx1 ADD y0,y0,cy1 ADD x1,x1,cx1 ADD y1,y1,cy1 ; BL drawcolouredicon ; depends on flag settings ; check to see if font manager has gone ga ga [ outlinefont LDR R14,systemfont TST R14,#&80000000 BEQ %FT00 LDR R1,[R10,#i_flags] ; R1 = flag word TST R1,#if_fancyfont ; it'll probably fail again. MOVEQ R14,#0 BICNE R14,R14,#&80000000 STR R14,systemfont BEQ druilp ] 00 Pull "handle,userblk,PC",VS ; error! 01 LDR R14,iconhandle ADD R14,R14,#1 STR R14,iconhandle ADD R10,R10,#i_size B druilp doneusericons CLRV Pull "handle,userblk,PC" ; ; Entry: handle-->window definition ; Exit: cx1,cy1 = window origin ; [careticonaddr], [areaCBptr] set up ; setwindowptrs Push "LR" ; LDR R14,caretdata+0 CMP R14,#nullptr Abs R14,R14,NE LDRNE R14,[R14,#w_icons] ; R14 --> start of icon list (NK 339) LDRNE R0,caretdata+4 ADDNE R14,R14,R0,LSL #i_shift STR R14,careticonaddr ; R14 --> addr of caret icon ; ADD R14,handle,#w_wax0 LDMIA R14,{R0,R1,cx0,cy0,cx1,cy1} SUB cx1,R0,cx1 ; cx1 <- x0-scx SUB cy1,cy0,cy1 ; cy1 <- y1-scy ; LDR R14,[handle,#w_areaCBptr] STR R14,areaCBptr ; for sprite plotting [ :LNOT: TrueIcon3 LDRB R14,[handle,#w_wbcol] STRB R14,work_back_colour ; 320nk, setup default background colour ] MOV R14,#0 STR R14,iconhandle ; for iconbar plotting ; Pull "PC" [ TrueIcon3 ; ; Entry: handle -> window definition ; Exit: true window colour words set up ; setwindowcolours ROUT EntryS "R3" MOV R14, #nullptr ; initialise all colours to -1 STR R14, truetitlefg ; ie not yet specified STR R14, truetitlebg STR R14, trueworkfg STR R14, trueworkbg STR R14, truescoutcolour STR R14, truescincolour STR R14, truetitlebg2 ; LDRB R14, [handle, #w_flags2] TST R14, #wf2_truecolour ; this bit set is a prerequisite BEQ %FT01 ; LDR R14, [handle, #w_flags] TST R14, #wf_icon3 BEQ %FT02 ; no title bar => definitely use w_title+4 as validation string ; LDR R14, [handle, #w_titleflags] TST R14, #if_indirected ANDNE R14, R14, #if_text :OR: if_sprite TEQNE R14, #if_sprite BEQ %FT01 ; w_title+4 is already put to another use in these cases ; 02 ; read validation string Push "R4" LDR R3, [handle, #w_title+4] ADRL R4, truetitlefg BL readtruecolours Pull "R4" ; 01 ; each word now holds the specified true colour, or -1 if not specified ; look up unspecified colours - must assume wf_realcolours is unset BL getpalpointer ; R14 -> Wimp palette ; LDR R3, truetitlefg CMP R3, #-1 BNE %FT10 LDRB R3, [handle, #w_tfcol] TEQ R3, #&FF ; special flag value? MOVEQ R3, #sc_black ; default to Wimp black ANDNE R3, R3, #&F LDR R3, [R14, R3, LSL #2] ; look up palette entry STR R3, truetitlefg 10 LDR R3, truetitlebg CMP R3, #-1 LDREQB R3, [handle, #w_tbcol] ANDEQ R3, R3, #&F LDREQ R3, [R14, R3, LSL #2] ; look up palette entry STREQ R3, truetitlebg ; LDR R3, trueworkfg CMP R3, #-1 LDREQB R3, [handle, #w_wfcol] ANDEQ R3, R3, #&F LDREQ R3, [R14, R3, LSL #2] ; look up palette entry STREQ R3, trueworkfg ; LDR R3, trueworkbg CMP R3, #-1 BNE %FT11 LDRB R3, [handle, #w_wbcol] TEQ R3, #&FF ; special flag value? MOVEQ R3, #sc_white ; default to Wimp white (yes, that's what the old Wimp did too...) ANDNE R3, R3, #&F LDR R3, [R14, R3, LSL #2] ; look up palette entry STR R3, trueworkbg 11 LDR R3, truescoutcolour CMP R3, #-1 LDREQB R3, [handle, #w_scouter] ANDEQ R3, R3, #&F LDREQ R3, [R14, R3, LSL #2] ; look up palette entry STREQ R3, truescoutcolour ; LDR R3, truescincolour CMP R3, #-1 LDREQB R3, [handle, #w_scinner] ANDEQ R3, R3, #&F LDREQ R3, [R14, R3, LSL #2] ; look up palette entry STREQ R3, truescincolour ; LDR R3, truetitlebg2 CMP R3, #-1 LDREQB R3, [handle, #w_tbcol2] ANDEQ R3, R3, #&F LDREQ R3, [R14, R3, LSL #2] ; look up palette entry STREQ R3, truetitlebg2 ; EXITS ] ; ; Entry: R1 = icon flags ; R2 --> icon data ; Exit: various ptrs and flags set up ; task swap can occur without userblk being set up !!! ; ASSERT border_normal =0 ; do main processing of flags + icon information seticonptrs TraceL font int_seticonptrs ROUT Trace fcol, "seticonptrs: icon flags ", X, R1 Push "R3,R10,LR" ; LDR R14,areaCBptr STR R14,thisCBptr STR R2,spritename ; MOV R14,#0 STR R14,validationstring STR R14,border_type MOV R14,#1 STR R14,lengthflags ; not null! MOV R14,#-1 STR R14,linespacing [ TrueIcon1 STR R14,truefgcolour STR R14,truebgcolour ] [ TrueIcon2 STR R14, truebgcolour2 STR R14, truewellcolour STR R14, truefacecolour STR R14, trueoppcolour ] [ TrueSelectionColours STR r14, trueselfgcolour STR r14, trueselbgcolour ] TST R1,#if_fancyfont ;If system font, use colours in flags MOVEQ R14,R1 ;If scalable font, use white & black. This might be changed later, if ; there's an F in the validation string. MOVNE R14,#(sc_white:SHL:ib_bcol):OR:(sc_black:SHL:ib_fcol) ASSERT ib_bcol > ib_fcol MOV R3,R14,LSR #ib_bcol STRB R3,fontbackground Trace fcol, "seticonptrs: (1) fontbackground ", X, R3 MOV R3,R14,LSR #ib_fcol AND R3,R3,#if_fcol:SHR:ib_fcol STRB R3,fontforeground Trace fcol, "seticonptrs: (1) fontforeground ", X, R3 ; TST R1,#if_indirected [ TrueIcon2 BLEQ mungetruecolours ] Pull "R3,R10,PC",EQ ; LDMIA R2,{R2,R3,R14} STR R2,spritename ; TST R1,#if_text ; unless text as well, STREQ R3,thisCBptr ; validation string = areaCBptr STRNE R3,validationstring STR R14,lengthflags ; if text, this must be <>0 [ TrueIcon2 BLEQ mungetruecolours ] Pull "R3,R10,PC",EQ ; ; check for line spacing ; Push "R2,R3" AcceptLoosePointer_NegOrZero R3,-1 CMP R3,R3,ASR #31 BEQ %FT01 BL pageiniconbartask MOV R2,#WimpValidation_Line BL findcommand BNE %FT01 ; MOV R2,#40 LDRB R14,[R3] ; shouldn't need to do this, but XOS_ReadUnsigned CMP R14,#"0" ; returning an error can trash MessageTrans' BLO %FT02 ; error buffers CMP R14,#"9" BHI %FT02 ; Push "R0,R1" MOV R0,#10 MOV R1,R3 SWI XOS_ReadUnsigned MOVVS R2,#40 Pull "R0,R1" 02 STR R2,linespacing 01 Pull "R2,R3" ; ; check for anti-aliased font colour field ; TST R1,#if_fancyfont BEQ %FT01 Push "R2,R3" AcceptLoosePointer_NegOrZero R3,-1 CMP R3,R3,ASR #31 BEQ %FT11 BL pageiniconbartask ; we need to access the task's data MOV R2,#WimpValidation_Font BL findcommand BNE %FT11 ; LDRB R2, [R3], #1 [ true ; slightly more robust (if less elegant) code: copes with incomplete/invalid specifier (eg "F0", "F9x" or even just "F") CMP R2, #' ' BLO %FT11 ; stop if terminated ORR R2, R2, #&20 CMP R2, #'0' BLO %FT11 CMP R2, #'9' SUBLS R2, R2, #'0' BLS %FT05 CMP R2, #'a' BLO %FT11 CMP R2, #'f' SUBLS R2, R2, #'a'-10 BHI %FT11 05 | ASCII_UpperCase R2,R14 Hex R2,R2 ; R2 = background colour ] STRB R2,fontbackground Trace fcol, "seticonptrs: (2) fontbackground ", X, R2 LDRB R2,[R3] [ true ; slightly more robust (if less elegant) code: copes with incomplete/invalid specifier (eg "F0", "F9x" or even just "F") CMP R2, #' ' BLO %FT11 ; stop if terminated ORR R2, R2, #&20 CMP R2, #'0' BLO %FT11 CMP R2, #'9' SUBLS R2, R2, #'0' BLS %FT05 CMP R2, #'a' BLO %FT11 CMP R2, #'f' SUBLS R2, R2, #'a'-10 BHI %FT11 05 | ASCII_UpperCase R2,R14 Hex R2,R2 ; R2 = foreground colour ] STRB R2,fontforeground Trace fcol, "seticonptrs: (2) fontforeground ", X, R2 11 Pull "R2,R3" 01 ; ; check for the border field ; Push "R0,R3" ; AcceptLoosePointer_NegOrZero R3,-1 CMP R3,R3,ASR #31 BLNE pageiniconbartask BLNE getborder ; attempt to define the border string ; Pull "R0,R3" [ TrueIcon2 ; ; check for a 24-bit colour specifier ; Push "R4" ADR R4, truefgcolour BL readtruecolours Pull "R4" | [ TrueIcon1 ; ; check for a 24-bit colour specifier ; Push "R2,R3" AcceptLoosePointer_NegOrZero R3,-1 CMP R3,R3,ASR #31 BEQ %FT14 BL pageiniconbartask MOV R2,#WimpValidation_Colour BL findcommand BNE %FT14 Push "R0,R1" ; LDRB R0,[R3] TEQ R0,#'/' ; if a '/' here then no foreground supplied MOV R1,R3 MOVEQ R3,#-1 BEQ %FT12 ; MOV R0,#16 MOV R1,R3 SWI XOS_ReadUnsigned ; read the foreground colour BVS %FT13 MOV R2,R2,LSL #8 STR R2,truefgcolour LDRB R0,[R1] TEQ R0,#'/' ; check for the / BNE %FT13 12 MOV R0,#16 ADD R1,R1,#1 SWI XOS_ReadUnsigned ; read the background colour MOVVC R2,R2,LSL #8 STRVC R2,truebgcolour 13 Pull "R0,R1" TST R1,#is_shaded BEQ %FT14 ; deal with shading... LDR R2,truefgcolour LDR R3,truebgcolour Push "R0,R12" BIC R12,R1,#is_inverted CMP R2,#-1 MOVNE R0,R2 BLNE inversefunc MOVNE R2,R0 CMP R3,#-1 MOVNE R0,R3 BLNE inversefunc MOVNE R3,R0 Pull "R0,R12" STR R2,truefgcolour STR R3,truebgcolour 14 Pull "R2,R3" TST R1,#is_inverted ; is the icon inverted BEQ %FT04 | TST R1,#is_inverted ; is the icon inverted BEQ %FT02 ] ; ; if the icon is inverted then swap around the various colours making it appear ; suitable. Note that we should include the highlight colour if required. ; LDR R0,border_type TEQ R0,#border_action TEQNE R0,#border_defaultaction BNE %FT02 ; if not sensible border then ignore ; LDR R0,border_highlight STRB R0,fontbackground ; then freak the background colour to something sensible ; Push "R3" ;320nk MOV R3,R0 TST R1, #if_fancyfont BICEQ R1,R1,#if_fcol :OR: if_bcol ORREQ R1,R1,R0,LSL #ib_fcol LDRB R0,fontforeground ; was LDR!! ORREQ R1,R1,R0,LSL #ib_bcol ; munge flags to contain the new fg/bg colours STRB R0,fontbackground STRB R3,fontforeground Pull "R3" [ TrueIcon1 B %FT04 02 TST R1, #if_text ; text+sprite icons don't swap TSTNE R1, #if_sprite BNE %FT04 ; LDR R0, truefgcolour ; swap the 24-bit colours here to save hassle later LDR R14, truebgcolour STR R0, truebgcolour STR R14, truefgcolour 04 | 02 ] ] TST R1,#if_sprite [ TrueIcon2 BLEQ mungetruecolours ] Pull "R3,R10,PC",EQ ; finished unless Sprite+Text ; AcceptLoosePointer_NegOrZero R3,-1 CMP R3,R3,ASR #31 ; no validation string? [ TrueIcon2 BLEQ mungetruecolours ] Pull "R3,R10,PC",EQ ; ; process validation string for sprite+text icon ; BL pageiniconbartask ; we need to access the task's data ; Push "R2" ; R2 --> text buffer MOV R2,#WimpValidation_Sprite BL findcommand ; R3 --> command found [ TrueIcon2 BLNE mungetruecolours ] Pull "R2,R3,R10,PC",NE ; leave sprite as text if not found ; BL scanname ; copy sprite name into buffer [ slabinout STR R1,two_sprite_save ] TST R1,#is_inverted ; if selected, choose the 2nd version [ TrueIcon2 BLEQ mungetruecolours ] Pull "R2,R3,R10,PC",EQ LDRB R14,[R3,#-1] ; was that a ","? TEQ R14,#"," ; if ended with ",", scan next name BICEQ R1,R1,#is_inverted ; prevent sprite being inverted too! BLEQ scanname [ TrueIcon2 BL mungetruecolours ] Pull "R2,R3,R10,PC" ; R2 --> original (text) buffer [ TrueIcon2 readtruecolours ROUT ; In: R3 -> validation string (or <= 0 to do nothing) ; R4 -> first word to write to (should be truefgcolour or truetitlefg) ; Out: [truefgcolour], [truebgcolour], [truebgcolour2], [truewellcolour], [truefacecolour], [trueoppcolour] OR ; [truetitlefg], [truetitlebg], [trueworkfg], [trueworkbg], [truescoutcolour], [truescincolour], [truetitlebg2] ; may each be modified according to validation string Entry "R0,R2,R3" AcceptLoosePointer_NegOrZero R3,-1 CMP R3,R3,ASR #31 BEQ %FT14 BL pageiniconbartask MOV R2,#WimpValidation_Colour BL findcommand BNE %FT14 Push "R0,R1" MOV R1, R3 readval_truefg LDRB R0, [R1] TEQ R0, #'/' ; if a '/' here then no foreground supplied BEQ readval_truebg MOV R0, #16 SWI XOS_ReadUnsigned ; read the foreground colour BVS %FT13 MOV R2, R2, LSL #8 STR R2, [R4] LDRB R0, [R1] TEQ R0, #'/' ; if not followed by a '/', then no other colours are supplied BNE %FT13 readval_truebg ADD R4, R4, #4 LDRB R0, [R1, #1] ! ; skip preceding '/' TEQ R0, #'/' ; if a '/' here then no background supplied BEQ readval_truebg2 MOV R0, #16 SWI XOS_ReadUnsigned ; read the background colour BVS %FT13 MOV R2, R2, LSL #8 STR R2, [R4] LDRB R0, [R1] TEQ R0, #'/' ; if not followed by a '/', then no other colours are supplied BNE %FT13 readval_truebg2 ADD R4, R4, #4 LDRB R0, [R1, #1] ! ; skip preceding '/' TEQ R0, #'/' ; if a '/' here then no slabbed-in background supplied BEQ readval_truewell MOV R0, #16 SWI XOS_ReadUnsigned ; read the slabbed-in background colour BVS %FT13 MOV R2, R2, LSL #8 STR R2, [R4] LDRB R0, [R1] TEQ R0, #'/' ; if not followed by a '/', then no other colours are supplied BNE %FT13 readval_truewell ADD R4, R4, #4 LDRB R0, [R1, #1] ! ; skip preceding '/' TEQ R0, #'/' ; if a '/' here then no well supplied BEQ readval_trueface MOV R0, #16 SWI XOS_ReadUnsigned ; read the well colour BVS %FT13 MOV R2, R2, LSL #8 STR R2, [R4] LDRB R0, [R1] TEQ R0, #'/' ; if not followed by a '/', then no other colours are supplied BNE %FT13 readval_trueface ADD R4, R4, #4 LDRB R0, [R1, #1] ! ; skip preceding '/' TEQ R0, #'/' ; if a '/' here then no light 3D supplied BEQ readval_trueopp MOV R0, #16 SWI XOS_ReadUnsigned ; read the light 3D colour BVS %FT13 MOV R2, R2, LSL #8 STR R2, [R4] LDRB R0, [R1] TEQ R0, #'/' ; if not followed by a '/', then no other colours are supplied BNE %FT13 readval_trueopp ADD R4, R4, #4 LDRB R0, [R1, #1] ! ; skip preceding '/' TEQ R0, #'/' ; if a '/' here then no dark 3D supplied [ :LNOT: TrueIcon3 BEQ %FT13 MOV R0, #16 SWI XOS_ReadUnsigned ; read the dark 3D colour MOVVC R2, R2, LSL #8 STRVC R2, [R4] | BEQ readval_truetitlebg2 MOV R0, #16 SWI XOS_ReadUnsigned ; read the dark 3D colour BVS %FT13 MOV R2, R2, LSL #8 STR R2, [R4] LDRB R0, [R1] TEQ R0, #'/' ; if not followed by a '/', then no other colours are supplied BNE %FT13 readval_truetitlebg2 ADD R4, R4, #4 LDRB R0, [R1, #1] ! ; skip preceding '/' TEQ R0, #'/' ; if a '/' here then no input focus supplied [ TrueSelectionColours BEQ readval_trueselbg | BEQ %FT13 ] MOV R0, #16 SWI XOS_ReadUnsigned ; read the input focus colour [ TrueSelectionColours BVS %FT13 MOV r2,r2,LSL #8 STR r2,[r4] | MOVVC R2, R2, LSL #8 STRVC R2, [R4] ] [ TrueSelectionColours LDRB R0, [R1] TEQ R0, #'/' ; if not followed by a '/', then no other colours are supplied BNE %FT13 readval_trueselbg ADD R4, R4, #4 LDRB R0, [R1, #1] ! ; skip preceding '/' TEQ R0, #'/' BEQ %FT13 MOV R0, #16 SWI XOS_ReadUnsigned MOVVC r2,r2,LSL #8 STRVC r2,[r4] ] ] 13 Pull "R0,R1" 14 CLRV EXIT mungetruecolours ROUT ; In: R1 = icon flags ; if fancy font, then [fontforeground] and [fontbackground] hold Wimp colours ; [truefgcolour], [truebgcolour], [truebgcolour2], [truewellcolour], [truefacecolour] and [trueoppcolour] ; hold specified true colours, or -1 if no specified true colour ; [border_type] is border type ; [border_highlight] is slabbed-in background Wimp colour ; Out: [truefgcolour], [truebgcolour] made valid, and adjusted for selection or shading ; [truewellcolour], [truefacecolour] and [trueoppcolour] made valid, and shaded if necessary ; R1 may be modified EntryS "R0,R2" BL getpalpointer ; R14 -> Wimp palette LDR R0, truefgcolour CMP R0, #-1 BNE %FT01 ; don't corrupt a 24-bit colour that was specified explicitly TST R1, #if_fancyfont LDRNEB R0, fontforeground MOVEQ R0, R1, LSR #ib_fcol AND R0, R0, #&F LDR R0, [R14, R0, LSL #2] ; look up palette entry STR R0, truefgcolour 01 LDR R0, truebgcolour CMP R0, #-1 BNE %FT01 ; don't corrupt a 24-bit colour that was specified explicitly TST R1, #if_fancyfont LDRNEB R0, fontbackground MOVEQ R0, R1, LSR #ib_bcol AND R0, R0, #&F LDR R0, [R14, R0, LSL #2] ; look up palette entry STR R0, truebgcolour 01 LDR R0, truebgcolour2 CMP R0, #-1 LDREQ R0, border_highlight ANDEQ R0, R0, #&F LDREQ R0, [R14, R0, LSL #2] ; look up palette entry STREQ R0, truebgcolour2 LDR R0, truewellcolour CMP R0, #-1 BNE %FT01 LDR R0, border_type TEQ R0, #border_defaultaction LDREQ R0, [R14, #sc_cream :SHL: 2] ; default = Wimp cream (default action) LDRNE R0, [R14, #sc_verylightgrey :SHL: 2] ; default = Wimp grey 1 (editable) STR R0, truewellcolour 01 LDR R0, truefacecolour CMP R0, #-1 LDREQ R0, [R14, #sc_white :SHL: 2] ; default = Wimp white STREQ R0, truefacecolour LDR R0, trueoppcolour CMP R0, #-1 BNE %FT01 LDR R0, border_type TEQ R0, #border_ridge TEQNE R0, #border_channel LDREQ R0, [R14, #sc_lightgrey :SHL: 2] ; default = Wimp grey 2 (shallow) LDRNE R0, [R14, #sc_middarkgrey :SHL: 2] ; default = Wimp grey 4 (normal) STR R0, trueoppcolour 01 TST R1, #is_inverted BEQ %FT01 LDR R0, border_type TEQ R0, #border_action TEQNE R0, #border_defaultaction BEQ %FT02 TST R1, #is_shaded TSTEQ R1, #if_sprite :OR: if_filled BEQ %FT03 ; normal inversion [ TrueSelectionColours LDR R3, trueselfgcolour CMP R3, #-1 LDREQ R3, truebgcolour LDR R2, trueselbgcolour CMP R2, #-1 LDREQ R2, truefgcolour | LDR R2, truefgcolour LDR R3, truebgcolour ] STR R3, truefgcolour STR R2, truebgcolour TST R1, #if_sprite ; deal with special cases ORREQ R1, R1, #if_filled B %FT01 03 ; "EOR" inversion LDR R2, truebgcolour LDR R3, =&FFFFFF00 EOR R0, R2, R3 ; necessary to ensure black inverts (compatibility) LDR R2, truefgcolour [ TrueIcon3 LDR R3, trueworkbg ; best guess at background colour | LDRB R3, work_back_colour ; best guess at background colour AND R3, R3, #&F LDR R3, [R14, R3, LSL #2] ; look up palette entry ] EOR R2, R2, R0 EOR R3, R3, R0 STR R2, truefgcolour STR R3, truebgcolour B %FT01 02 ; action button inversion LDR R0, truebgcolour2 STR R0, truebgcolour TST R1, #if_sprite ; deal with special cases ORREQ R1, R1, #if_filled 01 [ true TST R1, #if_sprite :OR: if_filled :OR: if_fancyfont ; should only apply to system font, for compatibility | TST R1, #if_sprite :OR: if_filled ] TSTEQ R1, #is_inverted [ TrueIcon3 LDR R2, trueworkbg | LDRB R2, work_back_colour AND R2, R2, #&F LDR R2, [R14, R2, LSL #2] ; look up palette entry ] STREQ R2, truebgcolour ; best guess for what background to antialias to TST R1, #is_shaded EXITS EQ ; must preserve flags [ true ADR R0, truefgcolour LDR R14, [R0] Push "R2, R14" MOV R2, #-1 BL fadetruecolour ; further bodge: if the faded icon fg matches the unfaded icon bg AND the window bg, reinstate the unfaded icon fg ; this fixes the questionable way CC fade their gadgets LDR R14, [R0] ADR R2, truebgcolour LDR R2, [R2] TEQ R14, R2 Pull "R2" TEQEQ R14, R2 Pull "R14" STREQ R14, [R0] ] LDR R0, border_type TEQ R0, #border_normal MOVNE R2, #-1 ; only bodge the background if a non-3D icon ADR R0, truebgcolour BL fadetruecolour MOV R2, #-1 [ false ADR R0, truefgcolour BL fadetruecolour ] ADR R0, truewellcolour BL fadetruecolour ADR R0, truefacecolour BL fadetruecolour ADR R0, trueoppcolour BL fadetruecolour EXITS ; must preserve flags LTORG fadetruecolour ROUT ; In: R0 -> palette entry to fade ; R2 = window background palette entry, or -1 to turn off special case ; Out: [R0] updated: grey, and half the distance from white (cf sprites, which are 1/4 the distance from white) Push "R1, R2, R4, R14" LDR R4, [R0] TEQ R4, R2 Pull "R1, R2, R4, PC", EQ ; leave icon background alone if it matches the work area background MOV R14, #&FF AND R1, R14, R4, LSR #8 ; extract red AND R2, R14, R4, LSR #16 ; extract green AND R3, R14, R4, LSR #24 ; extract blue MOV R14,#77 MUL R14,R1,R14 ; red *77 MOV R1,#150 MLA R14,R2,R1,R14 ; red *77 + green *150 RSB R3,R3,R3,LSL #3 ADD R14,R14,R3,LSL #2 ; red *77 + green *150 + blue *28 ADD R14,R14,#&7F ; Rounding ADD R14,R14,R14,LSL #8 ; Make 16 bit fractional ADD R14,R14,#&100 ; Rounding MOV R14,R14,LSR #16 ; Convert to 8bit luma RSBS R14, R14, #&FF ; get distance from white MOVMI R14, #0 ; just in case MOV R14, R14, LSR #1 ; divide by 2 RSB R14, R14, #&FF ; invert back MOV R4, R14, LSL #8 ORR R4, R4, R14, LSL #16 ORR R4, R4, R14, LSL #24 ; recombine to make &BBGGRR00 STR R4, [R0] Pull "R1, R2, R4, PC" ] scanname Push "LR" ; ADR R2,spritenamebuf STR R2,spritename ; [spritename] --> sprite name MOV R14,#12 ; max chars 01 LDRB R10,[R3],#1 ; get next char TEQ R10,#";" TEQNE R10,#"," MOVEQ R10,#0 ; terminate if ";" or "," or ctrl-char STRB R10,[R2],#1 SUBS R14,R14,#1 ; no terminator if 12 chars long Pull "PC",EQ CMP R10,#32 ; any ctrl-char also terminates BCS %BT01 ; Pull "PC" ; in R3 -> string to scan ; out R0 = result =0 ; R3 -> terminating character ; Preserves flags getnumber ROUT EntryS "R1-R2" MOV R0,#0 ; result =0 MOV R1,#10 ; Number base 10 LDRB R2,[R3],#1 SUB R2,R2,#'0' ; ASCII -> Numeric, ctrl's-> large +ve CMP R2,#10 ; is the character valid? MLALO R0,R1,R0,R2 ; R0=R1*R0+R2 BLO %BT10 ; loop back until all characters scanned 20 Debug bo,"getnumber result =>",R0 SUB R3,R3,#1 ; balance the stack and finished EXITS ; ; Entry: [redrawhandle] = window handle ; [iconhandle] = icon handle ; If swapping R1=icon flags. ; ; Exit: if this is the icon bar, the relevant task is paged in ; userblk preserved - this is incorrect if a task swap occurs ; If swapping, only if icon is indirected. pageiniconbartask EntryS ; LDR R14,redrawhandle CMP R14,#nullptr BEQ piibt_x1 LDR R0,iconbarhandle TEQ R0,R14 BNE piibt_x1 TST R1,#if_indirected BEQ piibt_x1 ; Push "R1-R4,R7,userblk" ; userblk not in use here! LDR R4,iconhandle BL findicon LDREQ R14,[R2,#icb_taskhandle] Task R14,EQ,"Icon bar redraw" ; Pull "R1-R4,R7,userblk" piibt_x1 EXITS ; preserve flags ; ; Entry: R0,R1 = window/icon handles (rel.) ; Exit: handle -> window definition, relevant task paged in ; userblk -> block for relevant task, if task swap occurred ; ; If swapping, page in the task only if icon is indirected. pageinicontask_R3R4 Push "R0-R4,LR" MOV R0,R3 MOV R1,R4 BL pageinicontask Pull "R0-R4,PC" pageinicontask EntryS ; MOV handle,R0 BL checkhandle BVS piit_x1 ; CMP R0,#nullptr ; is it system window? BEQ %FT01 ; CMP R1,#0 BLT %FT01 ; or a system icon? ; LDR R14,[handle,#w_icons] ADD R14,R14,R1,LSL #i_shift LDR R14,[R14,#i_flags] TST R14,#if_indirected BEQ piit_x1 01 LDR R14,iconbarhandle TEQ R0,R14 BEQ %FT01 ; LDR R14,[handle,#w_taskhandle] Task R14,,"Icon access" piit_x1 EXITS 01 Push "R1-R4,R7" MOV R4,R1 ; R1 = icon handle BL findicon LDREQ R14,[R2,#icb_taskhandle] Task R14,EQ,"Icon access (iconbar)" Pull "R1-R4,R7" EXITS ; preserve flags ;----------------------------------------------------------------------------- ; Draw icon, with regard to the inverting and shading flags ; Entry: R1 = flag word (including colours) ; R2 --> data ; x0,y0,x1,y1 = bounding box ; Exit : colours set up (if required) and icon drawn (if necessary) ;----------------------------------------------------------------------------- drawcolouredicon Push "cx0,cy0,cx1,cy1,LR" ; ADR R14,clipx0 ; check intersection FIRST! LDMIA R14,{cx0,cy0,cx1,cy1} CMP x0,cx1 CMPLT y0,cy1 CMPLT cx0,x1 CMPLT cy0,y1 ; Pull "cx0,cy0" Pull "cx1,cy1,PC",GE ; ; now set the colours ; [ TrueIcon2 ; ; this code covers every type of icon ; Push "R0-R9" LDR R0, border_type TEQ R0, #border_action TEQNE R0, #border_defaultaction BEQ %FT01 TST R1, #if_sprite :OR: if_filled TSTEQ R1, #is_shaded BNE %FT01 TST R1, #is_inverted BEQ %FT01 ; apply EOR inversion *before* main icon draw BL trueeorrectangle 01 Pull "R0-R9" BL icon_fg BL icon_bg [ outlinefont LDR R0,systemfont TEQ R0,#0 ; is the outline font defined? TSTEQ R1,#if_fancyfont | TST R1,#if_fancyfont ] TSTNE R1, #if_text BLNE setfancyfontcolours BLVC godrawicon tryshaded exitcicon Pull "cx1,cy1,PC" trueeorrectangle ; determine EOR colour from the window and icon background colours Push "R14" [ TrueIcon3 LDR R0, trueworkbg | BL getpalpointer LDRB R0, work_back_colour AND R0, R0, #&F LDR R0, [R14, R0, LSL #2] ] SWI XColourTrans_ReturnColourNumber MOV R1, R0 LDR R0, truebgcolour SWI XColourTrans_ReturnColourNumber EOR R1, R0, R1 ; we want the window background to be mapped to the icon background MOV R0, #&13 ; set background, EOR colours SWI XOS_SetColour BLVC solidrectangle CLRV Pull "PC" | TST R1,#if_sprite BNE ciconsprite ; TST R1,#if_fancyfont BNE ciconfancy TST R1,#if_filled BEQ ciconhollow ; EOR with background colour ; TST R1,#if_text ; BNE cicontext ; ; ordinary text or default ; - swap colours if inverted ; - AND colours if shaded ; cicontext TST R1,#is_shaded ANDNE R1,R1,#if_shadecols ; shade foreground & background TST R1,#is_inverted [ TrueIcon1 MOV R0,R1,LSR #ib_fcol ; get foreground colour BLEQ icon_fg BLNE icon_bg MOV R0,R1,LSR #ib_bcol ; get background colour BLEQ icon_bg BLNE icon_fg | MOV R0,R1,LSR #ib_fcol ; get foreground colour BLEQ foreground BLNE background MOV R0,R1,LSR #ib_bcol ; get background colour BLEQ background BLNE foreground ] ; [ outlinefont LDR R0,systemfont CMP R0,#0 ; is the outline font defined? TSTNE R1,#if_text ; and is the icon a text jobbie? BLNE ciconfancy2 ] ; BLVC godrawicon B exitcicon ; shading done already tryshaded [ false BVS exitcicon TST R1,#is_shaded ; NB do shading last! MOVNE R0,#(2:SHL:4):OR:(&80+2) BLNE int_setcolour ; GCOL 2,128+wimpcolour(2) BLNE solidrectangle ; AND with colour 2 ; | [ false ; don't need to do anything TST R1,#is_shaded LDRNE R14,tempworkspace+20 STRNEB R14,work_back_colour ] ] exitcicon Pull "cx1,cy1,PC" ciconsprite LDRB R0,fontbackground ; get background colour [ TrueIcon1 BL icon_bg ; in case background set | BL background ; in case background set ] BVS exitcicon ; TST R1,#if_text TSTNE R1,#is_inverted LDREQB R0,fontforeground ; R0 = foreground colour BEQ %FT01 TST R1,#if_filled BICNE R1,R1,#if_filled ; CORRUPTS R1!!! BLNE solidrectangle ; fill in normally [ TrueIcon1 LDRB R0,fontforeground BL icon_bg ; but invert the text LDRB R0,fontbackground 01 BL icon_fg ; (must be same as EOR colour) | LDRB R0,fontforeground BL background ; but invert the text LDRB R0,fontbackground 01 BL foreground ; (must be same as EOR colour) ] ; [ {FALSE} [ outlinefont LDR R14,systemfont TEQ R14,#0 TSTEQ R1,#if_fancyfont | TST R1,#if_fancyfont ] BLNE setfancyfontcolours ; ] BL godrawicon ; B exitcicon ciconfancy TST R1,#if_border LDRNEB R0,fontforeground ; colour in validation string [ TrueIcon1 BLNE icon_fg | BLNE foreground ] ; TST R1,#is_inverted LDREQB R0,fontbackground ; colour in validation string LDRNEB R0,fontforeground ; colour in validation string TST R1,#if_filled LDREQB R0,fontbackground [ TrueIcon1 BLNE icon_bg | BLNE background ] ciconfancy2 ; [ {False} BL setfancyfontcolours ; ] BL godrawicon B exitcicon ] setfancyfontcolours TraceL font Push "R1-R2,LR" ; [ TrueIcon3 LDR R2, truefgcolour LDR R1, truebgcolour BL settruefontcolours ; now true colours are guaranteed to be available | TST R1,#is_inverted MOV R14,R1 LDREQB R1,fontbackground LDRNEB R1,fontforeground LDREQB R2,fontforeground LDRNEB R2,fontbackground TST R14,#is_shaded BEQ %FT05 TST R14,#if_fancyfont ANDNE R1,R1,#2 ; 3.10 compat, but looks naff ANDNE R2,R2,#2 ANDEQ R2,R2,#4 ; for system font icons with outline font [ TrueIcon1 05 BL getpalpointer LDR R1, [R14, R1, LSL #2] ; R1 = physical background colour LDR R2, [R14, R2, LSL #2] ; R2 = physical foreground colour LDR R14,truefgcolour ; check for true colour overrides CMP R14,#-1 MOVNE R2,R14 LDR R14,truebgcolour CMP R14,#-1 MOVNE R1,R14 BL settruefontcolours | 05 BL setfontcolours ] ] ; Pull "R1-R2,PC" [ :LNOT: TrueIcon2 ciconhollow ; do shaded by munging its colours and pretending it's inverted ; this emulates the really naff way that 3.10 shades an icon TST R1,#is_shaded BEQ %FT05 ORR R1,R1,#is_inverted LDRB R14,work_back_colour BIC R14,R14,#3 ; how will it 'shade' ; note 3.10 use 2, but this looks bad with an outline font AND R14,R14,#15 ; make sure we don't overwrite BIC R1,R1,#15 :SHL: ib_bcol ; EOR colour = 0 ORR R1,R1,R14 ,LSL #ib_bcol ; EOR colour = back BIC 2 LDR R0,=&ffffffff BIC R0,R0,#15 :SHL: ib_fcol ORR R0,R0,#3 :SHL: ib_fcol ; yep, can be done more easilly, ; but this is so screwed it needs to be obvious! AND R1,R1,R0 ; 'shade' foreground EOR R1,R1,R14 ,LSL #ib_fcol ; cancel out EOR effect BIC R1,R1,#is_shaded ; stop munge later on 05 [ {TRUE} [ outlinefont LDR R0,systemfont ; 320nk background must be set up ; for antialiased fonts | MOV R0,#0 ] TEQ R0,#0 BEQ hollow_next TST R1,#is_inverted LDRB R0,work_back_colour STREQB R0,fontbackground BEQ hollow_next MOV R14,R1, LSR #ib_bcol EOR R0,R0,R14 STRB R0,fontbackground MOV R0,R1, LSR #ib_fcol EOR R0,R0,R14 AND R0,R0,#15 STRB R0,fontforeground MOV R0,R1, LSR #ib_bcol BL eorrectangle BIC R1,R1,#is_inverted TST R1,#if_border LDRNEB R0,fontforeground [ TrueIcon1 BLNE icon_fg ; needs to be set | BLNE foreground ; needs to be set ] BL godrawicon B tryshaded hollow_next ] TST R1,#is_inverted BNE %FT10 MOV R0,R1,LSR #ib_fcol [ TrueIcon1 BL icon_fg ; background colour not used | BL foreground ; background colour not used ] BLVC godrawicon B tryshaded ; 10 MOV R0,R1,LSR #ib_bcol MOV R14,R1, LSR #ib_fcol EOR R0,R0,R14 ; new foreground [ TrueIcon1 BL icon_fg | BL foreground ] BIC R1,R1,#is_inverted MOV R0,R1, LSR #ib_bcol BLVC eorrectangle ; EOR with background colour BLVC godrawicon B tryshaded eorrectangle [ false Push LR ; AND R0,R0,#&0F ORR R0,R0,#&80+&30 BL int_setcolour BLVC solidrectangle ; Pull PC | ; the old way (above) only worked sucessfully in 16 colour modes [ false Push "R1-R3,lr" LDRB R14,work_back_colour EOR R0,R0,R14 AND R0,R0,#&f ; bg+ib BL getpalpointer LDR R0,[R14,R0, LSL #2] MOV R2,R14 SWI XColourTrans_ReturnColourNumber MOV R1,R0 ; C(bg+ib) LDRB R0,work_back_colour ; work area background AND R0,R0,#&f LDR R0,[R2,R0, LSL #2] SWI XColourTrans_ReturnColourNumber ;C(bg) EOR R1,R0,R1 ;C(bg)+C(bg+ib) MOV R0,#&13 ; EOR action on background SWI XOS_SetColour BL solidrectangle Pull "R1-R3,PC" | ; the above demonstrates the mechanism, but we use a lookup table to improve performance Push "R1,lr" ADRL lr,inverselookup LDR R1,[lr] CMP R1,#-1 BLEQ findeorvalues ADRL lr,inverselookup AND R0,R0,#15 ADD lr,lr,R0, LSL #6 LDRB R0,work_back_colour AND R0,R0,#15 LDR R1,[lr,R0, LSL #2] MOV R0,#&13 SWI XOS_SetColour BL solidrectangle Pull "R1,PC" ] ] findeorvalues Push "R0-R5,lr" BL getpalpointer MOV R2,R14 ADRL R3,inverselookup+16*64 MOV R4,#15 05 MOV R5,#15 SUB R3,R3,#64 ; one row 10 EOR R0,R4,R5 LDR R0,[R2,R0, LSL #2] ; palette entry for colour SWI XColourTrans_ReturnColourNumber MOV R1,R0 ; C(bg+ib) LDR R0,[R2,R5, LSL #2] SWI XColourTrans_ReturnColourNumber ;C(bg) EOR R1,R0,R1 ;C(bg)+C(bg+ib) STR R1,[R3,R5, LSL #2] SUBS R5,R5,#1 BPL %BT10 SUBS R4,R4,#1 BPL %BT05 Pull "R0-R5,PC" ] ;----------------------------------------------------------------------------- ; Icon graphics routines - assumes colours already set up ; Entry : R1 = flag word ; R2 --> text/sprite name etc. ; x0,y0,x1,y1 = bounding box of icon ; [iconhandle] = handle of icon ;----------------------------------------------------------------------------- drawicon_system_sysf [ outlinefont Push "LR" LDR R14,systemfont Push "R14" MOV R14,#0 STR R14,systemfont ; Force this icon to use system font BL drawicon_system Pull "R14" STR R14,systemfont Pull "PC" | ; Fall through, it's already system font ] drawicon_system ; R1 = icon flags ; R2 -> icon data ; (R6, R7, R8, R9) = icon bbox TraceK font, "drawicon_system: flags " TraceX font, R1 TraceK font, ", data " TraceX font, R2 TraceNL font [ No32bitCode Push "LR" | ; Yucky yucky stacky stacky (omounts to Push "LR,CPSR") STR LR, [SP, #-8]! MRS LR, CPSR STR LR, [SP, #4] ] BL seticonptrs ; clear out validation string etc. [ TrueIcon3 LDR LR, truetitlefg ; forcibly reassert title truecolours STR LR, truefgcolour LDR LR, titlecolour STR LR, truebgcolour ] ; Pull "LR" ;drawicon TraceL font ; R1 = icon flags ; R2 -> icon data ; (R6, R7, R8, R9) = icon bbox ; TraceK font, "drawicon: flags " ; TraceX font, R1 ; TraceK font, ", data " ; TraceX font, R2 ; TraceNL font Push "cx0,cy0,cx1,cy1" ; ADR R14,clipx0 LDMIA R14,{cx0,cy0,cx1,cy1} CMP x0,cx1 CMPLT y0,cy1 CMPLT cx0,x1 CMPLT cy0,y1 [ No32bitCode Pull "cx0,cy0,cx1,cy1,LR" MOVGES PC,LR ; drop through | Pull "cx0,cy0,cx1,cy1" LDR LR,[SP,#4] BGE drawicon_out MSR CPSR_f,LR LDR LR,[SP],#8 ; woo ] godrawicon TraceL font ; R1 = icon flags ; R2 -> icon text TraceK font, "godrawicon: flags " TraceX font, R1 TraceK font, ", data " TraceX font, R2 TraceNL font EntryS "cx1,cy1" ; BL pageiniconbartask ; also called by seticonptrs (maybe) ; LDR R14,writeabledir Push "r14" [ FullIconClipping LDR r14,ThreeDFlags TST r14,#ThreeDFlags_FullIconClipping BEQ %FT01 Push "cx0-y1" ADR R14,clipx0 LDMIA R14,{cx0,cy0,cx1,cy1} ADR R14,oldclipx0 STMIA R14,{cx0,cy0,cx1,cy1} max x0,cx0 ; NB must result in non-null window max y0,cy0 ; since the rectangles intersect min x1,cx1 min y1,cy1 BL graphicswindow Pull "cx0-y1" 01 ] TST R1,#if_numeric MOVNE R14,#0 STRNE R14,writeabledir ; TST R1,#if_filled [ ThreeDPatch BLNE iconfilledCheckMenu | BLNE iconfilled ; this checks for if_fancyfont ] TST R1,#if_sprite BLNE iconsprite ; IS allowed if if_text set!!! BVC %FT01 TST R1,#if_indirected BEQ enddr CLRV 01 TST R1,#if_text BLNE icontext ; also checks for if_fancyfont TST R1,#if_border BLNE iconborder enddr [ FullIconClipping LDR r14,ThreeDFlags TST r14,#ThreeDFlags_FullIconClipping ADRNE R14,oldclipx0 LDMNEIA R14,{x0,y0,x1,y1} BLNE graphicswindow ] Pull "r14" STR R14,writeabledir EXITS ; preserves flags (errors lost) [ :LNOT:No32bitCode drawicon_out MSR CPSR_f,LR LDR PC,[SP],#8 ; woo ] icontext TraceL font ; R1 = icon flags ; R2 -> icon text TraceK font, "icontext: flags " TraceX font, R1 TraceK font, ", string " TraceS font, R2 TraceNL font Push "R1-R4,LR" LDR R14,linespacing ; is this a formatted icon? CMP R14,#-1 BNE iconformatted ; Push "R3,x0-y1" LDR R3,validationstring BL getborder BL adjustforborder ; attempt to adjust for border specified BL findtextorigin ; [spaceinicon] ==> does it fit?, adjust cx1 Pull "R3,x0-y1" ; Pull "R1-R4,PC",VS ; depends on [hascaret], too ; ; if icon is too big, ensure that it is clipped ; [ RO4 ; MB FIX assume icon is always too big so that top and bottom are clipped properly. ; LDR R14,spaceinicon ; CMP R14,#6 ; needs at least 3*dx space left ; BPL %FT01 ; end MB FIX [ FullIconClipping LDR r14,ThreeDFlags TST r14,#ThreeDFlags_FullIconClipping BNE %FT01 ] | LDR R14,spaceinicon CMP R14,#6 ; needs at least 3*dx space left BPL %FT01 ] ; Push "cx0-y1" ADR R14,clipx0 LDMIA R14,{cx0,cy0,cx1,cy1} ADR R14,oldclipx0 STMIA R14,{cx0,cy0,cx1,cy1} max x0,cx0 ; NB must result in non-null window max y0,cy0 ; since the rectangles intersect min x1,cx1 min y1,cy1 BL graphicswindow Pull "cx0-y1" 01 ; ; if sprite+text icon, and (inverted or not filled), fill area just round text ; EOR R14,R1,#if_filled TST R14,#is_inverted TSTEQ R14,#if_filled TSTNE R14,#if_sprite BEQ %FT02 [ ThreeDPatch LDR r14,ThreeDFlags TST r14,#ThreeDFlags_NoIconBgInTransWindows BEQ %FT90 ; if clearing the background for icons in transparent windows is disabled then skip this bit LDR r14,redrawhandle CMP r14,#nullptr BEQ %FT90 Abs r14,r14 LDRB r14,[R14,#w_wbcol] TEQ r14,#&FF ; if window background is transparent TSTEQ r1,#is_inverted ; and the icon is not inverted BEQ %FT02 ; then don't plot the rectangle 90 ] LDRB R14,[R2] ; is the text null? CMP R14,#32 BICCC R1,R1,#if_filled ; don't fill if null rectangle BCC %FT02 ; [ ThreeDPatch ORR R1,R1,#if_filled ; now we must fill the background! Push "r0,cx0-cy1" LDR R14,text_y0 ADD cy1,cy1,R14 CMP cx1,x0 ; don't draw outside icon! MOVLT cx1,x0 CMP cy1,y0 MOVLT cy1,y0 LDR R14,writeabledir TEQ R14,#0 SUBNE R14,cx1,x0 SUBNE cx1,x1,R14 CMP cx1,x1 ; don't draw outside icon! MOVGT cx1,x1 MOV cx0,cx1 MOV cy0,cy1 LDR cy1,[sp,#4*4] LDR R14,temp_text_height ADD cy1,cy1,R14 LDR R14,text_width LDR R0,writeabledir TEQ R0,#0 ADDEQ cx1,cx1,R14 SUBNE cx1,cx1,r14 CMP cx1,x0 ; don't draw outside icon! MOVLT cx1,x0 CMP cx1,x1 ; don't draw outside icon! MOVGT cx1,x1 CMP cy1,y1 MOVGT cy1,y1 ; LDR R14,dx ; make inclusive ; SUB cx1,cx1,R14 ; LDR R14,dy ; SUB cy1,cy1,R14 ; cx0-cy1 now contain the rectangle to plot Push "handle" TST r1,#is_inverted BNE %FT92 LDR r14,ThreeDFlags TST r14,#ThreeDFlags_RemoveIconBackgrounds BEQ %FT92 MOV r0,r1,LSR #ib_bcol LDR handle,redrawhandle Debug threedpatch,"redraw handle = ",handle CMP handle,#nullptr BEQ %FT92 Abs handle,handle 93 LDRB r14,[handle,#w_wbcol] Debug threedpatch,"Window bg colour = ",r14 Debug threedpatch,"Icon bg colour = ",r0 TST r1,#if_fancyfont LDRNEB r0,fontbackground TEQ r0,r14 BEQ %FT90 92 Push "cx0-y1" ; cx0-cy1 and x0-y1 Pull "x0-y1" bl solidrectangle Pull "x0-y1" b %FT91 90 BIC r1,r1,#if_filled ; the icon isn't actually filled now. Debug threedpatch,"Calling ploticonbackgroundsprite",cx0,cy0,cx1,cy1,handle bl ploticonbackgroundsprite 91 Pull "handle" Pull "r0,cx0-cy1" | ; NOT ThreeDPatch ORR R1,R1,#if_filled ; now we must fill the background! Push "cx1,cy1" LDR R14,text_y0 ADD cy1,cy1,R14 CMP cx1,x0 ; don't draw outside icon! MOVLT cx1,x0 CMP cy1,y0 MOVLT cy1,y0 MOV R0,#4 ; LDR R14,writeabledir TEQ R14,#0 SUBNE R14,cx1,x0 SUBNE cx1,x1,R14 CMP cx1,x1 ; don't draw outside icon! MOVGT cx1,x1 ; BL plotcxy1 ; PLOT R0,cx1,cy1 (lower-left) LDR cy1,[sp,#1*4] [ {FALSE} TST R1,#is_inverted LDREQ R14,temp_text_height ;use real height! LDRNE R14,text_y1 | LDR R14,temp_text_height ] ADD cy1,cy1,R14 LDR R14,text_width ; LDR R0,writeabledir TEQ R0,#0 ADDEQ cx1,cx1,R14 SUBNE cx1,cx1,r14 CMP cx1,x0 ; don't draw outside icon! MOVLT cx1,x0 ; CMP cx1,x1 ; don't draw outside icon! MOVGT cx1,x1 CMP cy1,y1 MOVGT cy1,y1 LDR R14,dx ; make inclusive [ false ADD cx1,cx1,R14 LDR R14,dx_1 BIC cx1,cx1,R14 | SUB cx1,cx1,R14 ] LDR R14,dy SUB cy1,cy1,R14 ; [ {FALSE} [ outlinefont LDR R0,systemfont TEQ R0,#0 ; is it a system font? TSTEQ R1,#if_fancyfont | TST R1,#if_fancyfont ] MOVNE R0,#4 MOVEQ R0,#&67 | MOV R0,#&67 ] ; BL plotcxy1 ; PLOT R0,cx1,cy1 (upper-right) ; Pull "cx1,cy1" ] 02 LDR LR,writeabledir CMP LR,#0 BEQ %FT94 ; SUB r14,cx1,x0 SUB cx1,x1,r14 SUB cx1,cx1,#16 Push "R1" [ BlendedFonts ADRL R0,writedirreverse | ADR R0,writedirreverse ] MOV R1,#writedirreverse_len SWI XOS_WriteN ; poke the write direction for the cursor Pull "R1" 94 MOV R0,#4 BL plotcxy1 ; move to a sensible position ; [ outlinefont LDR LR,systemfont TEQ LR,#0 TSTEQ R1,#if_fancyfont | TST R1,#if_fancyfont ] BEQ %FT95 ; if not fancy font then ignore [ outlinefont BL remembercurrentfont ] Push "R0-R7" BL setfancyfontcolours ;get the font to use [ outlinefont TST R1, #if_fancyfont LDREQ R3, systemfont MOVNE R3, R1, LSR #ib_fontno ; get the correct font handle | MOV R3, R1, LSR #ib_fontno ; select appropriate font ] ; R1 = flags for icon ; R2 -> string to paint ; R3 = handle for icon font LDR R0, redrawhandle Trace menuw, "icontext: painting icon for handle ", X, R0 BIC R0, R0, #3 ; get the real pointer LDR R0, [R0, #w_taskhandle] ; R0 = handle of the task that owns this window (-1 for menus) Trace menuw, "icontext: task handle ", X, R0 ;We have to fix up the font string if the window is a menu, and not ; writable. CMP R0, #-1 BNE icontext_pushfontstring AND R0, R1, #15 :SHL: 12 TEQ R0, #15 :SHL: 12 TEQNE R0, #14 :SHL: 12 ; test for both types of writable ;Invert Z flag MOVNE R0, #0 MOVEQ R0, #1 TEQ R0, #0 icontext_pushfontstring Trace menuw, "icontext: icon flags ", X, R1 MOV R0, R1 [ CnP MOV R7, #nullptr ] BL pushfontstring BNE icontext_dont_justify ;Get max index value for menu entry TST R0, #if_indirected MOVNE R3, #bignum MOVEQ R3, #11 AND R14,R0,#if_esg CMP R14,#13 :SHL: ib_esg ; check for esg 13 - if it isn't (could be 12 BEQ icontext_dont_justify ; for a non-writable menu icon) don't munge it [ outlinefont BL fixupfontstring ; only call for non-writable icons ] MOV R2, #2_10001 B icontext_paint icontext_dont_justify MOV R2, #2_10000 icontext_paint [ BlendedFonts TST R0, #if_filled [ RO4 LDREQ LR,ThreeDFlags TSTEQ LR,#ThreeDFlags_NoFontBlending ] ORREQ R2, R2, #1:SHL:11 ] ; LDR R0,systemfont ; TEQ R0,#0 ; ORRNE R2,R2,#2 ; rub out box required LDR R0,writeabledir TEQ R0,#0 ORRNE R2,R2,#1 :SHL: 10 ; write right to left ADD R0, SP, #cx1*4 ADD R0, R0, R7 LDMIA R0, {R3-R4} ; pick up cx1 and cy1 Trace menuw, "icontext: painting string ", S, R1 ADD R3,R3,#2 ; KJB - attempt to nobble it a bit ADDNE R3,R3,#12 ; BJGA - attempt to fix right-to-left printing SWI XFont_Paint ; then paint the string [ BlendedFonts BVC %FT10 TST R2, #1:SHL:11 BICNE R2, R2, #1:SHL:11 SWINE XFont_Paint 10 ] [ outlinefont BLVS LoseFont LDRVS R0,systemfont ORRVS R0,R0,#&80000000 STRVS R0,systemfont ] LDR R0,tool_list ; 320nk TEQ R0,#0 BLEQ restore_tool_list ; make sure there's something there ; just in case we're in the middle of ; plotting a title bar, for instance. ADD SP,SP,R7 ; balance the stack for an easy life 94 Pull "R0-R7" B %FT90 writedirnormal = 23,16,0,&FD,0,0,0,0,0,0 writedirnormal_len * .-writedirnormal writedirreverse = 23,16,2,&FD,0,0,0,0,0,0 writedirreverse_len * .-writedirreverse ALIGN 95 ; set up R4 = character to display as (if 0, display real string) Push "R2" MOV R4,#0 ; no char to print as LDR R3,validationstring AcceptLoosePointer_NegOrZero R3,-1 CMP R3,R3,ASR #31 ; R3 = 0/-1 ==> no validation string BEQ %FT96 MOV R2,#WimpValidation_Display BL findcommand LDREQB R4,[R3],#1 TEQEQ R4,#"\\" LDREQB R4,[R3] 96 Pull "R2" TST R1,#if_indirected ; limit 12 chars unless indirected MOVEQ R3,#12 MOVNE R3,#bignum wrcrlp SUBS R3,R3,#1 LDRCSB R0,[R2],#1 CMPCS R0,#32 BCC %FT90 CMP R4,#32 MOVCS R0,R4 ; use R4 if it's ok SWI XOS_WriteC BVC wrcrlp 90 LDR LR,writeabledir CMP LR,#0 BEQ %FT94 ; Push "R0,R1" ADR R0,writedirnormal MOV R1,#writedirnormal_len SWI XOS_WriteN ; poke the write direction for the cursor Pull "R0,R1" 94 [ No32bitCode Push "R0,x0,y0,x1,y1,PC" | MRS R14,CPSR Push "R0,x0,y0,x1,y1,R14" ] ; [ RO4 ; MB FIX ; as we removed the other side of this removing this as well might be a good idea ; LDR R14,spaceinicon ; CMP R14,#6 ; needs at least 3*dx space left ; BPL %FT01 ; end MB FIX | LDR R14,spaceinicon CMP R14,#6 ; needs at least 3*dx space left BPL %FT01 ] ; [ FullIconClipping LDR r14,ThreeDFlags TST r14,#ThreeDFlags_FullIconClipping ADREQ R14,oldclipx0 LDMEQIA R14,{x0,y0,x1,y1} BLEQ graphicswindow | ADR R14,oldclipx0 LDMIA R14,{x0,y0,x1,y1} BL graphicswindow ] 01 Pull "R0,x0,y0,x1,y1,R14" [ No32bitCode TEQP R14,#0 ; restore PSR | MSR CPSR_f,R14 ; restore PSR ] Pull "R1-R4,PC" plotcxy1 Push "R1,R2,LR" MOV R1,cx1 MOV R2,cy1 SWI XOS_Plot Pull "R1,R2,PC" ; yeehhaaa! ; draw formatted text in icon ; Entry: R1 = icon flags ; R2 --> text string ; x0,y0,x1,y1 = coordinates of surrounding box ; [linespacing] = amount to leave between lines ; Exit: R1-R4, PC pulled from stack iconformatted TraceL L40 ASSERT x0=R6 ; can't use R6..R9 TraceK L40, "iconformatted: flags " TraceX L40, R1 TraceK L40, ", string " TraceS L40, R2 TraceNL L40 Push "R5-R6,R10" [ outlinefont ;Should we use a scalable font? This new code allows L40 icons to be ; antialiased for the first time: previously, if_fancyfont was ; ignored. TST R1, #if_fancyfont MOVNE R3, R1, LSR #ib_fontno ;get the font handle LDREQ R3, systemfont TEQEQ R3, #0 BNE iconformatted_fancy ] ; draw, or return info on, formatted system font text ; Entry: R1 = icon flags ; R2 -> text string ; x0-y1 = icon bounding box ; [linespacing] = distance between baselines ; [linecount] <> 0 => just return number of lines required ; Exit: if returning number, R0-R5, R10, R14 corrupted, [linecount] contains line count, PC pulled from stack ; else: R5, R6, R10, R1-R4, PC pulled from stack iconformatted_system TraceL L40 MOV R0,R2 ; R0 -> string MOV R10,#0 ; R10 = lines so far LDR R14,dy ; R14 = ??? MOV R5,#0 iconformatted_skip_spaces LDRB R14,[R0],#1 TEQ R14,#" " ; skip leading spaces BEQ iconformatted_skip_spaces SUB R0,R0,#1 MOV R2,R0 ; scan from here ; R2 -> string (ignoring leading spaces) MOV R3,R2 ; last split position ; SUB R4,x1,x0 ; R4 = width of icon in OSU MOV R4,R4,ASR #4 ; divide by 16 (char width) ; R4 = width of icon in characters SUB R4,R4,#2 ; margin of 1 char, and R4=nchars-1 CMP R4,#5 MOVLT R4,#5 ; R4 = max no of chars - 1 ; R4 = width of icon, minimum 5 ;Get the length of the string iconformatted_length LDRB R14,[R0],#1 CMP R14,#" " ; look for space or ctrl-char SUBLS R3,R0,#1 ; R3 --> separator SUBLO R0,R0,#1 ; don't pass terminator SUBCSS R4,R4,#1 ; decrement counter BCS iconformatted_length ; stop on terminator/19 chars ; R3 -> terminator SUBS R3,R3,R2 ; R3 = length of string SUBEQS R3,R0,R2 ; if no split char, do all so far ADD R0,R2,R3 ; go back to split char (skip later) Push "R2,R3",HI ADDHI R10,R10,#1 ; no of lines to do LDRHI R14,linespacing ADDHI R5,R5,R14 BHI iconformatted_skip_spaces [ StretchErrorText LDR R3, linecount TEQ R3, #0 STRNE R10, linecount ; store the number of lines required ADDNE sp, sp, R10, LSL#3 ; skip line markers on stack Pull "PC", NE ] ; R5 = height of text in OSU ; R10 = no of lines ; on stack are pairs [addr,size] of strings (last one on top) Push "R5,R10" ; ADD R3,x0,x1 ADD R2,y0,y1 ; R3,R2 = coordinates of centre of icon * 2 Pull "R5,R6" LDR R14,linespacing ; last line is only 32 high, not SUB R5,R5,R14 ; [linespacing] high (if you see ADD R5,R5,#32 ; what I mean) ; R5 = height of string in OSU ; R6-> string to paint TEQ R6,#0 BEQ iconformatted_system_done SUB R2,R2,R5 ; R2 = y-coord of bottom line MOV R2,R2,ASR #1 MOV R3,R3,ASR #1 LDR R14,dy_1 ADD R2,R2,#31 SUB R2,R2,R14 BIC R2,R2,R14 ; round R2 down to pixels iconformatted_system_paint_line LDR R0,[sp,#4] ; length of next item SUB R1,R3,R0,LSL #3 MOV R0,#4 SWI XOS_Plot Pull "R0,R1" ; get ptr/length SWI XOS_WriteN LDR R14,linespacing ADD R2,R2,R14 SUBS R6,R6,#1 BNE iconformatted_system_paint_line iconformatted_system_done Pull "R5-R6,R10" Pull "R1-R4,PC" [ outlinefont ; draw, or return info on, formatted outline font text ; Entry: R1 = icon flags ; R2 -> string to paint ; R3 = font handle ; ((R6, R7), (R8, R9)) = icon bbox ; [linespacing] = distance between baselines ; [linecount] <> 0 => just return number of lines required ; Exit: if returning number, R0-R6, R10, R14 corrupted, [linecount] contains line count, PC pulled from stack ; else: R5, R6, R10, R1-R4, PC pulled from stack iconformatted_fancy TraceL L40 TraceK L40, "iconformatted: icon bbox is ((" TraceD L40, R6 TraceK L40, ", " TraceD L40, R7 TraceK L40, "), (" TraceD L40, R8 TraceK L40, ", " TraceD L40, R9 TraceK L40, "))" TraceNL L40 Push "R7-R9,R11" ADD R4, R7, R9 MOV R4, R4, ASR #1 ; R4 = y-coord of icon centre SUB R5, R9, R7 ; R5 = total height of icon (OSU) Trace L40, "iconformatted: icon height ", D, R5 BL remembercurrentfont BL setfancyfontcolours [ CnP MOV R7, #nullptr ] BL pushfontstring MOV R0,R3 SWI XFont_SetFont ; unfortunately, because we plot a line at a time the fact that pushfontstring ; has prepended the font handle, for lines 2... this is somewhat useless if the ; app has been using the font manager! MOV R0, R1 MOV R10, R7 ; R0 -> string to paint ; R10 = difference in stack SUB R1, R8, R6 ; R1 = width available in icon (OSU) ADD R8, R6, R8 MOV R8, R8, ASR #1 ; R8 = x-coord of icon centre MOV R6, R9 ; R6 = depth so far Trace L40, "iconformatted: initial icon top ", D, R6 SUBS R1, R1, #16 MOVLE R1, #0 SWI XFont_Converttopoints MOV R9, R1 ; R9 = width available in icon (mpt) MOV R1, R0 ; R1 -> string MOV R11, #0 ; R11 = indicator for pass number iconformatted_fancy_next_pass ;On the first pass, save R1, R5 on the stack; on the second, get ; them back TEQ R11, #0 Push "R1, R5", EQ Pull "R1, R5", NE BEQ iconformatted_fancy_first_pass ; R11 = number of lines formatted [ StretchErrorText LDR R0, linecount TEQ R0, #0 BEQ %FT06 STR R11, linecount ADD sp, sp, R10 ; balance stack after pushfontstring Pull "R7-R9, R11, PC" ; exit with number of lines required in [linecount] 06 ] LDR R0, linespacing MUL R11, R0, R11 SUB R11, R11, R0 ; again, the last line has height 32, ADD R11, R11, #32 ; not [linespacing] ; R11 = total height of lines required Trace L40, "iconformatted: height of lines ", D, R11 Trace L40, "iconformatted: icon height ", D, R5 [ false CMP R11, R5 ; KJB: This isn't done in the system MOVGT R11, R5 ; font case! ] ; R11 = total height available for lines Trace L40, "iconformatted: height available ", D, R11 SUB R11, R5, R11 ; R11 = space in icon after lines are printed (>= 0) Trace L40, "iconformatted: => total gap ", D, R11 Trace L40, "iconformatted: old icon top ", D, R6 ;Work out the position of the first line to paint SUB R6, R6, R11, ASR #1 SUB R6, R6, #28 LDR R14, dy_1 BIC R6, R6, R14 Trace L40, "iconformatted: new icon top ", D, R6 MOV R11, #-1 iconformatted_fancy_first_pass B iconformatted_fancy_reinit iconformatted_fancy_skip_spaces ADD R1, R1, #1 iconformatted_fancy_paint_lines LDRB R0, [R1, #0] CMP R0, #" " BEQ iconformatted_fancy_skip_spaces CMP R0,#0 MOVEQ R5,#0 ; NK, added to cope with spaces at end of string BEQ iconformatted_fancy_next MOV R0, R1 ; R0 -> string ;Scan string to the required length MOV R2, R9 MOV R3, #bignum MOV R4, #" " MOV R5, #bignum TraceK L40, "iconformatted: Font_StringWidth (first time)" TraceNL L40 SWI XFont_StringWidth ; R1 corrupted ; R2 = x-offset up to termination (mpt) ; R5 = length that will fit ;There is the ghastly possibility that R5 = 0 (probably because ; there are no spaces in the string). If so, try again with no ; split character. TEQ R5, #0 BNE iconformatted_width_ok MOV R1, R0 MOV R2, R9 MOV R3, #bignum MOV R4, #-1 MOV R5, #bignum TraceK L40, "iconformatted: Font_StringWidth (second time)" TraceNL L40 SWI XFont_StringWidth ; R0 corrupted ; R2 = x-offset up to termination (mpt) ; R5 = length that will fit ;In fact, there is STILL the ghastly possibility that R5 = 0 - now, ; it's presumably because the characters are just TOO BIG!! ; Deal with this by setting R5 to 1 and R2 to the width of the ; icon. TEQ R5, #0 BNE iconformatted_width_ok TraceK L40, "iconformatted: Font_StringWidth given up" TraceNL L40 MOV R5, #1 MOV R2, R9 iconformatted_width_ok ; R1 corrupted ; R2 = x-offset up to termination (mpt) ; R5 = length that will fit SWI XFont_ConverttoOS MOV R1, R0 ;put R1 back TraceK L40, "iconformatted: Font_StringWidth (" TraceS L40, R1 TraceK L40, ") -> width " TraceD L40, R2 TraceK L40, " OSU, length " TraceD L40, R5 TraceNL L40 ;Work out where to paint the string ;Count on the first pass; paint on the second. CMP R11, #-1 ADDNE R11, R11, #1 BNE iconformatted_fancy_next MOV R7, R5 LDR R14, linespacing MOV R4, R6 SUB R6, R6, R14 ; y -:= linespacing SUB R3, R8, R2, ASR #1 ; x := centre - x/2 [ BlendedFonts [ RO4 MOV R2, #1 :SHL: 4 :OR: 1 :SHL: 7 LDR LR,ThreeDFlags TST LR,#ThreeDFlags_NoFontBlending ORREQ R2,R2,#1:SHL:11 | MOV R2, #1 :SHL: 4 :OR: 1 :SHL: 7 :OR: 1 :SHL: 11 ; as below + blend bit ] | MOV R2, #1 :SHL: 4 :OR: 1 :SHL: 7 ;Font_OS_Units | Font_GivenLength ] ;Push "R6" ;ADD R6,R6,#32 ; system text is top-left, font paint bottom-left SWI XFont_Paint [ BlendedFonts [ RO4 BVC %FT01 TST R2,#1:SHL:11 BICEQ R2, R2, #1:SHL:11 SWIEQ XFont_Paint 01 | BICVS R2, R2, #1:SHL:11 SWIVS XFont_Paint ] ] BLVS LoseFont LDRVS R0,systemfont ORRVS R0,R0,#&80000000 STRVS R0,systemfont ;Pull "R6" LDR R0,tool_list ; 320nk TEQ R0,#0 BLEQ restore_tool_list ; make sure there's something there ; just in case we're in the middle of ; plotting a title bar, for instance. iconformatted_fancy_next ADD R1, R1, R5 ;output from Font_StringWidth iconformatted_fancy_reinit LDRB R0, [R1, #0] TEQ R0, #:CHR: 0 BNE iconformatted_fancy_paint_lines Trace L40, "iconformatted: lines of text to format ", D, R11 ;Loop to do the painting on the first pass; continue on the second CMP R11, #-1 BEQ %FT99 ;320nk CMP R11, #0 BNE iconformatted_fancy_next_pass MOV R11, #-1 B iconformatted_fancy_next_pass 99 ADD SP, SP, R10 ;balance stack after pushfontstring Pull "R7-R9,R11" Pull "R5-R6,R10" Pull "R1-R4,PC" ] ; Find origin of text (depends on flags) ; Entry: R1,R2 = flag word/data ptr ; x0,y0,x1,y1 = bounding box of icon ; [hascaret] ==> does the caret have to be considered? ; Exit : cx1,cy1 = coords of LHS of text ; ; Sprite+Text case: ; ----------------- ; Vertical: ; V ==> both vertically centred <== as before ; HR~V ==> text at top, sprite at bottom ; ~V ==> text at bottom, sprite at top ; Horizontal: ; ~V ~H~R ==> both at left <== as before ; ~V ~H R ==> both at right <== as before ; ~V H ==> both centred <== as before ; V ~H~R ==> sprite at left, text +6 units to right (LJ) ; V H~R ==> both centred (text visible) <== as before ; V ~H R ==> text at left, sprite at right ; V H R ==> sprite at left, text at right (RJ) ; L * 1:SHL:0 ; only 1 of L,R,H set R * 1:SHL:1 H * 1:SHL:2 T * 1:SHL:3 ; only 1 of T,B,M set B * 1:SHL:4 V * 1:SHL:5 X * 1:SHL:6 ; text is just to the right of sprite text_lookup DCB L :OR: V ; ~V ~H ~R ~S DCB L :OR: B ; ; ~V ~H ~R S <-- new DCB R :OR: V ; ~V ~H R ~S DCB R :OR: B ; ; ~V ~H R S <-- DCB H :OR: V ; ~V H ~R ~S DCB H :OR: B ; ; ~V H ~R S <-- DCB H :OR: V ; ~V H R ~S DCB H :OR: T ; ; ~V H R S <-- DCB L :OR: V ; V ~H ~R ~S DCB X :OR: V ; ; V ~H ~R S <-- DCB R :OR: V ; V ~H R ~S DCB L :OR: V ; ; V ~H R S <-- DCB H :OR: V ; V H ~R ~S DCB H :OR: V ; ; V H ~R S <-- DCB H :OR: V ; V H R ~S DCB R :OR: V ; ; V H R S <-- ASSERT (.-text_lookup)=16 findtextorigin Push "cx0,cy0,LR" ; BL textwidth ; cx1 <- width of text (& select font) Pull "cx0,cy0,PC",VS STR cx1,text_width SUB R14,x1,x0 SUB R14,R14,cx1 ; is this too long? STR R14,spaceinicon ; used when displaying the icon CMP r14,#0 BGE %FT01 TST R1,#if_sprite ; sprite? BNE %FT01 TST R1,#if_hcentred ORRNE R1,R1,#if_rjustify BICNE R1,R1,#if_hcentred 01 ; ASSERT if_sprite = 2_00010 ASSERT if_border = 2_00100 ASSERT if_hcentred = 2_01000 ASSERT if_vcentred = 2_10000 ; BIC R14,R1,#if_border ; move rjustify bit into range TST R1,#if_rjustify ORRNE R14,R14,#if_border AND R14,R14,#2_11110 ; mask out 4 bits ADR R0,text_lookup LDRB R0,[R0,R14,LSR #1] ; R0 = flag byte ; TST R0,#X BEQ %FT01 ASSERT cy0 = R3 ; no need to stash this ASSERT cx1 = R4 BL spritesize ; R3,R4 = sprite size (R0 preserved) ADD cx1,x0,R3 ADD cx1,cx1,#6 ; left-justified, just after sprite B %FT02 01 TST R0,#L ADDNE cx1,x0,#6 ; cx1 <- x0 + 3*dx TST R0,#H SUBNE cx1,x1,cx1 SUBNE cx1,cx1,x0 ; width of box - width of text ADDNE cx1,x0,cx1,ASR #1 TST R0,#R SUBNE cx1,x1,cx1 SUBNE cx1,cx1,#6 ; cx1 <- cx1 - 3*dx 02 Push cx1 BL textheight ; cy0,cy1 = top/bottom of text (rel) Pull cx1 STR cy0,text_y0 STR cy1,text_y1 ; ; R0 preserved TST R0,#T SUBNE cy1,y1,cy1 ; origin = y1 - cy1 (at top) TST R0,#V ADDNE cy1,cy1,cy0 ; cy1 = 2*midpoint of text ADDNE R14,y0,y1 ; R14 = 2*midpoint of icon SUBNE R14,R14,cy1 MOVNE cy1,R14,ASR #1 ; now cx1,cy1 = origin of text TST R0,#B SUBNE cy1,y0,cy0 ; origin = y0 - cy0 (at bottom) ; now for fancy system font get baseline to that of ordinary system font (4 OS) [ {FALSE} LDR R14,systemfont TEQ R14,#0 ADDNE cy1,cy1,#2 ADDNE cy1,cy1,cy0, ASR #1 ] 01 Pull "cx0,cy0" ; ; now decide whether we must move the origin to incorporate the caret ; LDR R14,hascaret ; 0 ==> this icon has the caret TEQ R14,#0 Pull "PC",NE ; not in this icon! ; ; bestx = (x0+x1)/2 - caretx ; x1 = x0 - 3*dx + [spaceinicon] ; x0 = x0 + 3*dx ; if bestx > cx1 ; then if cx1 < x0 then cx1 = min(x0,bestx) ; else if cx1 > x1 then cx1 = max(x1,bestx) ; Push "R1,cx1,x0,x1" ; LDR R1,caretx ; offset of caret from text origin ; Debug sc,"caretx, x0, x1, cx1=",R1,x0,x1,cx1 ; ADD R14,x0,x1 RSB R1,R1,R14,ASR #1 ; R1 = (x0+x1)/2 - caretx ; SUB x1,x0,#6 ADD x0,x0,#6 ; include margins LDR R14,spaceinicon ADD x1,x1,R14 ; CMP R1,cx1 BLE %FT01 ; if bestx > cx1 then ; ; { CMP cx1,x0 ; if cx1 < x0 then MOVLT cx1,x0 ; { cx1 = x0 CMPLT R1,cx1 ; if bestx<x0 then cx1 = bestx MOVLT cx1,R1 ; } B %FT02 ; } 01 ; else CMP cx1,x1 ; { if cx1 > x1 then MOVGT cx1,x1 ; { cx1 = x1 CMPGT R1,cx1 ; if bestx>x1 then cx1 = bestx MOVGT cx1,R1 ; } 02 ; } Pull "R1,R14" ; R14 = old offset before caret bits SUB R14,cx1,R14 STR R14,caretscrollx ; offset due to presence of caret ; Debug sc,"caretscrollx =",R14 ; Pull "x0,x1,PC" ; ; Scan text width ; Entry: R1,R2 = flags, data ptr ; Exit : cx1 = width of text (OS coords) ; textwidth TraceL font Push "LR" [ outlinefont LDR R14,systemfont TEQ R14,#0 TSTEQ R1,#if_fancyfont | TST R1,#if_fancyfont ] BEQ getordwidth [ outlinefont LDR R0, currentfont TEQ R0, #0 BNE textwidth_current_font_known Push "R0-R3" SWI XFont_CurrentFont ;save the current font handle in a safe place STRVC R0, currentfont STRVC R1, currentbg STRVC R2, currentfg STRVC R3, currentoffset ;if V is set, everything is going to slow down horribly (calling ; Font_CurrentFont on every call to textwidth), but it will ; still work Trace font, "textwidth: current font is ", X, R0 ; NK 349 MOV R0,#0 MOV R1,#0 SWI XFont_SwitchOutputToBuffer CLRV ; make sure we're on the screen! Pull "R0-R3" textwidth_current_font_known ] ASSERT (cx1=R4) Push "R1-R3,R5-R7" [ outlinefont TST R1, #if_fancyfont LDREQ R3, systemfont MOVNE R3, R1, LSR #ib_fontno ; get the correct font handle | MOV R3, R1, LSR #ib_fontno ; select appropriate font ] ; R3 = font handle to use for text Push "R3" STR R1,tempworkspace+28 [ CnP MOV R7, #nullptr ] BL pushfontstring LDR R0,[SP,R7] ; stack has moved!!! ; R1 -> string ;320nk redone this bit to use scanstring and set CORRECT height at same time [ {FALSE} MOV R2, #0 MOV R3, #bignum MOV R4, #bignum MOV R5, #bignum SWI XFont_ScanString ] ; SWI XFont_StringBBox ; get width and height BL my_StringBBox ; correct screen BBox ; unlike Font_StringBBox!! ADD SP, SP, R7 ; balance the stack for a happy life ADD SP, SP, #4 Pull "R1-R3,R5-R7,PC",VS ; SUB R1,R3,R1 ; SUB R2,R4,R2 ; SWI XFont_ConverttoOS ; already in OS LDRVC R14,dx ADDVC cx1,R1,R14 , LSL #1 ; cx1 = offset in OS coords STRVC R2,temp_text_height TraceK font, "textwidth done" TraceNL font Pull "R1-R3,R5-R7,PC" ;;=================================================================== ;; my_StringBBox returns width and height of a string ;; Entry R1 points to string ;; Exit R1 width of string in OS units, R2 height above baseline ;;=================================================================== my_StringBBox ; Let's do the job properly this time: ; * Font_ScanString *can* be used to return the width instead of the bounding box ; * if_fancyfont icons might as well be measured the same way as the desktop font ; * icons with text above the sprite don't need the height trimming down Entry "R1,R7,R8" MOV R2, #0 MOV R3, #bignum MOV R4, #bignum SWI XFont_ScanString ; pushfontstring always puts font-selection control at start, so R0 not needed MOV R1, R3 ; x offset to end of string MOV R2, #0 ; dummy value SWI XFont_ConverttoOS ; results are already pixel-aligned LDR R3, tempworkspace+28 ; retrieve icon flags EOR R3, R3, #if_rjustify :OR: if_vcentred :OR: if_hcentred ; flip bits to make comparisons easier TST R3, #if_sprite TSTNE R3, #if_vcentred TSTNE R3, #if_rjustify :OR: if_hcentred LDREQ R2, systemfonty1 ; unless we've got a text+sprite icon with text below sprite, use full system font height LDRNE R5, [sp] ; get original R1 (if we're dropping through) STR R1, [sp] ; store width where it will be reloaded into R1 BNE %FT00 CLRV EXIT 00 ; Now we've still got to find the height using a Font_CharBBox loop, due to rounding errors in the ; Font Manager's string bounding box code (PRM 3-463). However, we can make some simplifications, based upon ; knowledge of what pushfontstring will have given us (ie only printable characters and font/colour changes) MOV R7, #0 ; cumulative maximum (starts at 0, so we'll always go up to the baseline at least) [ UTF8 LDRB R8, alphabet ; set up for us by pushfontstring 01 TEQ R8, #ISOAlphabet_UTF8 LDRNEB R1, [R5], #1 MOVEQ R4, #6 MOVEQ R6, R5 BLEQ convert_UTF8_to_UCS4 ; may return -1 for malformed characters MOVEQ R1, R6 ADDEQ R5, R5, R4 CMP R1, #-1 ; malformed character? LDREQ R1, =&FFFD ; use special glyph for the purpose | 01 LDRB R1, [R5], #1 ] TEQ R1, #0 ; pushfontstring always null-terminates BEQ %FT02 TEQ R1, #26 ; font change? LDREQB R0, [R5], #1 ; set R0 to hold font handle BEQ %BT01 [ CnP TEQ R1, #19 ; colour change? ADDEQ R5, R5, #8-1 ; skip BEQ %BT01 ] MOV R2, #1:SHL:4 ; return OS units SWI XFont_CharBBox LDRVS R4, systemfonty1 CMP R4, R7 ; compare top of bbox with cumulative maximum MOVGT R7, R4 B %BT01 02 MOV R2, R7 CLRV EXIT LTORG getordwidth Push "R2" MOV cx1,#0 LDR R14,dx getllp LDRB R0,[R2],#1 CMP R0,#32 ADDCS cx1,cx1,#16 ; constant character width BCS getllp ; Pull "R2,PC" ; ; Entry: R1 = flag word for icon ; Exit: cy0,cy1 = bottom/top of text (rel. to MOVE command) ; ASSERT cy0=R3 ASSERT cy1=R5 textheight TraceL font Push "R0-R2,R4,LR" ; [ outlinefont LDR R14,systemfont TEQ R14,#0 TSTEQ R1,#if_fancyfont | TST R1,#if_fancyfont ] LDREQ cy1,dy ; (upper origin is exclusive) SUBEQ cy0,cy1,#32 STREQ cy1,temp_text_height Pull "R0-R2,R4,PC",EQ ; [ outlinefont TST R1,#if_fancyfont LDREQ cy1,systemfonty1 LDREQ cy0,systemfonty0 Pull "R0-R2,R4,PC",EQ ] MOV R0,R1,LSR #ib_fontno Trace font, "textheight: reading info for font ", X, R0 SWI XFont_ReadInfo MOVVC cy1,R4 MOVVC cy0,R2 CLRV Pull "R0-R2,R4,PC" ; R0 preserved for icontext ; ; First calculate sprite origin ; (see findtextorigin for details of flag settings) ; Entry: R1,R2 = sprite flags, data ptr ; Exit: [spriteX], [spriteY] remembered ; sprite_lookup DCB L :OR: B ; ~V ~H ~R ~T DCB L :OR: T ; ; ~V ~H ~R T <-- new DCB R :OR: B ; ~V ~H R ~T DCB R :OR: T ; ; ~V ~H R T <-- DCB H :OR: B ; ~V H ~R ~T DCB H :OR: T ; ; ~V H ~R T <-- DCB H :OR: B ; ~V H R ~T DCB H :OR: B ; ; ~V H R T <-- DCB L :OR: V ; V ~H ~R ~T DCB L :OR: V ; ; V ~H ~R T <-- DCB R :OR: V ; V ~H R ~T DCB R :OR: V ; ; V ~H R T <-- DCB H :OR: V ; V H ~R ~T DCB H :OR: V ; ; V H ~R T <-- DCB H :OR: V ; V H R ~T DCB L :OR: V ; ; V H R T <-- ASSERT (.-sprite_lookup)=16 iconsprite Push "R0-R5,LR" ; BL spritesize ; R3,R4 = size of sprite (OS units) ; ASSERT if_sprite = 2_00010 ASSERT if_border = 2_00100 ASSERT if_hcentred = 2_01000 ASSERT if_vcentred = 2_10000 ; BIC R14,R1,#if_border:OR:if_sprite TST R1,#if_rjustify ORRNE R14,R14,#if_border TST R1,#if_text ORRNE R14,R14,#if_sprite AND R14,R14,#2_11110 ; mask out 4 bits ADR R0,sprite_lookup LDRB R0,[R0,R14,LSR #1] ; R0 = flag byte ; LDR R5,writeabledir TEQ R5,#0 BNE %FT01 TST R0,#L B %FT02 01 TST R0,#R 02 MOVNE R3,x0 ; left-justified TST R0,#H ADDNE R14,x0,x1 ; x coord = (x0+x1-width)/2 SUBNE R14,R14,R3 MOVNE R3,R14,ASR #1 ; centred LDR R5,writeabledir TEQ R5,#0 BNE %FT01 TST R0,#R B %FT02 01 TST R0,#L 02 SUBNE R3,x1,R3 ; right-justified ; TST R0,#T SUBNE R4,y1,R4 ; sprite at top TST R0,#V ADDNE R14,y0,y1 ; y coord = (y0+y1-height)/2 SUBNE R14,R14,R4 MOVNE R4,R14,ASR #1 ; R4 = origin of sprite TST R0,#B MOVNE R4,y0 ; not centred ==> at bottom ; STR R3,spriteX ; may be needed for inverting/shading STR R4,spriteY ; [ TrueIcon2 LDR R5, border_type TEQ R5, #border_action TEQNE R5, #border_defaultaction BICEQ R1, R1, #is_inverted ; never invert sprites in action buttons ] [ PlotSpritesFromPalette MOV R5,#8+16 ; plot sprite with mask using palette | MOV R5,#8 ; plot sprite with mask ] BL wimp_SpriteOp_putsprite ; uses [spritename] and R1 (flags) exitspricon STRVS R0,[sp] Pull "R0-R5,PC" ; ; Entry: R1 = icon flags ; [spritename] --> sprite name (set up by seticonptrs) ; Exit: R3,R4 = sprite size (OS units) ; spritesize Push "R0,LR" BL cachespritedata [ RO4 :LOR: true MOVVS r3,#0 ; if the call failed then the sprite probably MOVVS r4,#0 ; doesn't exist so return 0 for width and height BVS %FT01 ] LDR R14,sprite_log2px MOV R3,R3,LSL R14 LDR R14,sprite_log2py MOV R4,R4,LSL R14 ; exit: R3,R4 = sprite size (OS units) TST R1,#if_halfsize MOVNE R3,R3,ASR #1 MOVNE R4,R4,ASR #1 01 CLRV Pull "R0,PC" ; must preserve R0 for icontext code ; nb: foreground colour should be restored! ; in x0-y1 contain the bounding box of the area to plot around ; out - iconborder LDR R0,border_type Debug borders,"border type to plot =>",R0 CMP R0,#border_max ; is it still valid? ADDCC PC,PC,R0,LSL #2 ; if so then despatch, B hollowrectangle ; otherwise use default single pixel jobbie B hollowrectangle B plot_slabout B plot_slabin B plot_ridge B plot_channel B plot_action B plot_default B plot_editable iconfilled B solidrectangle ; fill the background of the icon [ ThreeDPatch iconfilledCheckMenu TST r1,#is_inverted ; if it's inverted BNE solidrectangle LDR r0,ThreeDFlags TST r0,#ThreeDFlags_TexturedMenus BEQ solidrectangle LDR r0,redrawhandle CMP r0,#nullptr BEQ solidrectangle Abs r0,r0 LDR r0,[r0,#w_taskhandle] CMP r0,#-1 ; if it's not a menu BNE solidrectangle AND r0,r1,#&F0000 TEQ r0,#&D0000 ; writable icons have esg set to &D BEQ %FT01 TEQ r0,#&C0000 ; the main menu item has ESG 12 BNE solidrectangle [ true ; see argument in createsubmenu TST r1,#if_sprite | ; 4.02 code TST r1,#if_text TSTNE r1,#if_sprite ; if it's not a text+sprite icon ] BEQ solidrectangle 01 Push "cx0-cy1,handle,lr" Push "x0-y1" Pull "cx0-cy1" LDR handle,redrawhandle Abs handle,handle BL ploticonbackgroundsprite Pull "cx0-cy1,handle,pc" ] ;;---------------------------------------------------------------------------- ;; Wimp_ReadPixTrans ;; call to allow user programs to find out what translation table to use ;; Entry: R0 = 0 / &100 / &200 ==> system / name ptr / sprite ptr ;; R1 --> sprite area (if R0 > 0) ;; R2 --> sprite name (if R0 < &200), else sprite ptr ;; R6 --> 4-word table to contain factors (0 ==> don't do it) ;; R7 --> 4-word table to contain pixel translation table (0==>don't) ;; Exit: [R6] contains the scale factors (4 words) ;; [R7] contains the pixel translation table (16 bytes, word-aligned) ;; ;; This call should not be used in any mode > 8BPP, nor should it be called ;; for sprites which have a depth > 4BPP as it will not return a sensibly sized ;; table - you have been warned! ;;---------------------------------------------------------------------------- SWIWimp_ReadPixTrans MyEntry "ReadPixTrans" CMP R0,#&100 MOVLO R1,#0 ; use system area if R0 < &100 MOV R14,#0 CMP R0,#&200 MOVLO R14,#1 ; lengthflags ==> is R2 a name/sprite? STR R14,lengthflags STR R1,thisCBptr ; used by cachespritedata STR R2,spritename ; used by cachespritedata BL cachespritedata BVS ExitWimp ; CMP R6,#0 ADRNE R14,sprite_factors LDMNEIA R14,{R1-R4} STMNEIA R6,{R1-R4} ; copy factors out ; CMP R7,#0 LDRNE R14,pixtable_at CMPNE R14,#0 LDMNEIA R14,{R1-R4} STMNEIA R7,{R1-R4} ; copy pixtrans out (NB word-aligned) ; B ExitWimp ;;---------------------------------------------------------------------------- ;; Rationalise sprite scaling factors ;; Entry: R0,R1 sprite's eigx/eigy ;; R5,R6 mode's eigx/eigy ;; R2 --> where to store the factors ;; Exit: R0,R1,R5,R6 corrupted ;; [R2] factors stored (xmul,ymul,xdiv,ydiv) ;;---------------------------------------------------------------------------- rationalisefactors Entry MOV R14,#1 ; all factors are ?:1 or 1:? so make R0:R5, R1:R6 ; into this form CMP R0,R5 MOVEQ R0,#1 MOVEQ R5,#1 MOVLT R5,R14,LSL R5 MOVLT R5,R5, LSR R0 MOVLT R0,#1 MOVGT R0,R14,LSL R0 MOVGT R0,R0, LSR R5 MOVGT R5,#1 CMP R1,R6 MOVEQ R1,#1 MOVEQ R6,#1 MOVLT R6,R14,LSL R6 MOVLT R6,R6, LSR R1 MOVLT R1,#1 MOVGT R1,R14,LSL R1 MOVGT R1,R1, LSR R6 MOVGT R6,#1 STMIA R2,{R0-R1,R5-R6} ; store the scaling block EXIT ;;---------------------------------------------------------------------------- ;; Mode-independent sprite code ;; Entry: [spritename] --> sprite name ;; [thisCBptr] --> sprite area ;; [lengthflags] ==> is R2 a name ptr or a sprite ptr? ;; Exit: R3,R4 = sprite size (pixels) ;; mode data set up if different input mode from last time ;;---------------------------------------------------------------------------- cachespritedata Entry "R1-R2,R5-R7" MOV R2,#1 STRB R2,selecttable_crit ; entering critical period for pixtable LDR R2,lengthflags CMP R2,#0 ; absolute pointer? LDR R2,spritename BLNE cachespriteaddress MOVVC R0,#&200+SpriteReason_ReadSpriteSize SWIVC XOS_SpriteOp ; read information about the sprite BVS %FT92 ; ; R2 -> sprite in area ; LDR R7,[R2,#spImage] LDR R14,[R2,#spTrans] CMP R7,R14 ; min(image,trans) MOVHI R7,R14 LDR R14,pixtable_at CMP R14,#0 ; is a pixtable defined? BEQ %FT10 TEQ R7,#spPalette ; does it have a palette? LDREQ R14,sprite_lastmode TEQEQ R6,R14 ; no, so have we already cached this information? BEQ %FT92 10 MOV R0,R6 ; R0 = mode of sprite TEQ R7,#spPalette MOVNE R6,#-1 ; if it has a palette then corrupt last mode STR R6,sprite_lastmode Push "R2,R3-R4" ; R2 -> sprite, R3,R4 = height / width MOV R1,#VduExt_Log2BPP SWI XOS_ReadModeVariable STRVC R2,sprite_log2bpp ; get the depth of the sprite MOVVC R1,#VduExt_XEigFactor SWIVC XOS_ReadModeVariable STRVC R2,sprite_log2px ; get the X scaling factor (pixels => OS units) MOVVC R1,#VduExt_YEigFactor SWIVC XOS_ReadModeVariable STRVC R2,sprite_log2py ; get the Y scaling factor (pixels => OS units) Pull "R2,R3-R4",VS BVS %FT92 LDR R1,sprite_log2bpp LDR R6,log2bpp TEQ R1,R6 ; any special translating? LDR R0,sprite_log2px LDR R5,log2px TEQEQ R0,R5 LDR R1,sprite_log2py LDR R6,log2py TEQEQ R1,R6 ; any special scaling? MOVEQ R14,#0 MOVNE R14,#-1 STRB R14,sprite_needsfactors ; may be modified later ADR r2,sprite_factors BL rationalisefactors Pull "R1" ; R1 -> sprite MOV R2,#-1 MOV R3,#-1 ; convert to the current mode [ Medusa MOV R5,#(1:SHL:0) :OR: 1:SHL:1 ; Use mode's palette if sprite has none | MOV R5,#(1:SHL:0) ] ; ; we must now attempt to cope with the dilemma of sorting out the correct ; mapping table for the sprite. ; ; in earlier versions of the Window Manager it made no attempt to cope ; with different depth sprites other than 1,2 or 4BPP so we will break ; new ground and go boldly where no larma has been parping before. ; LDR R14,sprite_log2bpp Debug ic,"Sprite bpp, palette",R14,R7 CMP R14,#3 ; is it 8,16 or 32BPP? CMPLT R7,#(spPalette+4) ; or does it have a palette? BLT %FT02 LDR R0,baseofromsprites ; might have 8+ bpp sprites in ROM now LDR R4,[R0,#saEnd] ADD R4,R0,R4 ; R4 -> end of ROM sprite area CMP R1,R0 CMPHS R4,R1 ; is sprite in ROM? LDRLO R0,baseofsprites ; no, use RAM sprite area ; 320nk Medusa fix B %FT10 ; ; sprite is in a depth less than 8BPP so take the current palette and munge ; it based on the translation table defined in workspace ; 02 LDR R0,[R1,#spMode] ; R0 = mode of sprite ADRL R1,temppaltable ; R1 -> temporary palette area Push "R0-R3,R5" BL getpalpointer ; R14 -> palette to be used LDR R4,sprite_log2bpp CMP R4,#1 ADRLTL R4,transtable1 ; R4 => translation 1BPP ADREQL R4,transtable2 ; translation 2BPP ADRGTL R4,transtable4 ; translation 4BPP MOV R5,#15 05 LDRB R3,[R4,R5] ; get index into real palette LDR R3,[R14,R3,LSL #2] BIC R3,R3,#&000000FF ; R3 = &BBGGRR00 STR R3,[R1,R5,LSL #2] SUBS R5,R5,#1 BPL %BT05 ; loop back copying the data Pull "R0-R3,R5" 10 MOV R4,#0 ; R4 =0 read table size SWI XColourTrans_SelectTable BVS %FT90 ; exit LDR R14,pixtable_at TEQ R14,#0 ; does the pixtable exist? LDRNE R14,pixtable_size CMP R14,R4 ; is it big enough? BHS %FT20 Push "R0-R3" LDR R2,pixtable_at CMP R2,#0 ; is there a pixel table defined yet? MOVNE R0,#ModHandReason_Free BLNE XROS_Module ; free it if there is - ignoring errors MOV R2,#0 STR R2,pixtable_at ; mark as the pix table has been released MOV R0,#ModHandReason_Claim MOV R3,R4 BL XROS_Module ; attempt to claim a new buffer big enough STRVC R2,pixtable_at STRVC R3,pixtable_size ; store pointer and define the size STRVS R0,[SP] Pull "R0-R3" BVS %FT90 ; return if it errors 20 MOV R6,R4 ; R6 = size of table generated (first time) LDR R4,pixtable_at ASSERT ?selecttable_args = 4*6 ADR R7,selecttable_args STMIA R7,{R0-R1,R2-R3,R4,R5} ; cache entry parameters for the translation Debug ic,"Sprite src mode, src pptr, dest mode, dest pptr",R0,R1,R2,R3 SWI XColourTrans_SelectTable BVS %FT90 ; return if not important CMP R6,#256 BHI %FT40 ; if its greater than 8bpp then we can ignore it (was GT) 35 SUBS R6,R6,#1 ; decrease the index into the table BMI %FT90 ; return if end of the world reached LDRB R14,[R4,R6] TEQ R14,R6 ; colour number = index? (1:1 mapped) BEQ %BT35 40 MOV R14,#-1 STRB R14,sprite_needsfactors ; mark as needing translation 90 Pull "R3-R4" 92 MOV R14, #0 STRB R14, selecttable_crit ; passed the critical moment for pixtable EXIT ;.............................................................................. ; in [spritename] --> sprite name ; [thisCBptr] --> sprite area ; [lengthflags] ==> R2 -> sprite name or sprite? ; out R2 -> sprite ; R0 corrupt area_System * 0 area_Wimp * 1 cachespriteaddress ROUT Entry "R1,R3" [ debugsprite LDR LR,spritename ] DebugS sprite,"cachespriteaddress: ",LR,12 LDR R0,lengthflags CMP R0,#0 ; absolute pointer to the sprite? LDREQ R2,spritename ; R2 -> sprite EXIT EQ LDR R1,thisCBptr ; R1 -> sprite pool CMP R1,#nullptr ; trap area pointer -1 (none) MOVEQ R1,#area_Wimp CMP R1,#area_Wimp ; if its the Wimp or above BCS %FT10 MOV R0,#3 SWI XOS_ReadDynamicArea MOV R1,R0 ; R1 -> system sprite pool 10 TEQ R1,#area_Wimp ; Wimp sprite pool or user specified? BNE %FT20 LDR R0,list_at CMP R0,#nullptr ; is there a list allocated? BEQ %FT15 ; no, its flagged as invalid CMP R0,#0 BNE %FT13 BL makespritelist LDR R0,list_at ; resolve pointer 13 CMP R0,#nullptr BEQ %FT15 ; if not valid still then return BL getspriteaddr STRVC R2,spritename ; store as pointer to the sprite MOVVC R0,#0 STRVC R0,lengthflags ; speed up 'cos makes it go faster EXIT 15 [ SpritePriority Debug sprite,"Looking in high-priority sprite area" LDR R1,baseofhisprites | Debug sprite,"Looking in RAM" LDR R1,baseofsprites ; R1 -> RAM based pool ] BL checkforsprite EXIT VC ; return if it has been found LDR R1,[R0] LDR R2,=ErrorNumber_Sprite_DoesntExist TEQ R1,R2 BNE %FT25 ; if sprite not found then return R2 =0 [ SpritePriority Debug sprite,"Looking in low-priority sprite area" LDR R1,baseoflosprites | Debug sprite,"Looking in ROM" LDR R1,baseofromsprites ] 20 BL checkforsprite EXIT VC LDR LR,[R0] ; error number returned LDR R2,=ErrorNumber_Sprite_DoesntExist TEQ LR,R2 BNE %FT25 ; if not then return with R2 =0 [ SpritePriority LDR LR,baseoflosprites | LDR LR,baseofromsprites ] TEQ LR,R1 ; Searching wimp areas? BEQ %FT25 ; Yes then exit ; As a last resort if searching user area then now try wimp area Debug sprite,"Looking in Wimp area" LDR R3,thisCBptr ; R3 -> pool MOV R14,#area_Wimp STR R14,thisCBptr ; mark as being Wimp BL cachespriteaddress STR R3,thisCBptr ; restore (original) pool pointer 25 DebugE sprite,"Sprite not found " MOVVS R2,#0 EXIT ;.............................................................................. ; in R1 -> sprite area to be checked ; [spritename] --> sprite name to look for ; out R2 -> sprite checkforsprite ROUT Push "LR" LDR R0,=&100+SpriteReason_SelectSprite LDR R2,spritename ; R2 -> sprite name SWI XOS_SpriteOp ; VC => R2 -> sprite Pull "PC" ;;---------------------------------------------------------------------------- ;; Graphics routines - used for various graphic effects ;;---------------------------------------------------------------------------- ; ; Entry: R0 bits 0..3 = wimp colour that text is to be set to ; R0 bit 7 = fg / bg (1 ==> bg colour) ; Exit: text (vdu 4) colour set up appropriately ; SWIWimp_TextColour MyEntry "TextColour" Push "R0,R3" AND R3,R0,#&80 ; fg/bg flag AND R0,R0,#&0F BL getpalpointer LDR R0,[R14,R0,LSL #2] ; physical colour to use SWI XColourTrans_SetTextColour STRVS R0,[SP] Pull "R0,R3" ; B ExitWimp ; ; Entry: R0 = colour/action to be set up ; bits 0..3 = colour (Wimp colour, in range 0..15) ; bits 4..6 = GCOL action ; bit 7 = fg / bg (1 ==> bg colour) ; SWIWimp_SetColour MyEntry "SetColour" Push R0 BL int_setcolour ADDVS sp,sp,#4 BVS ExitWimp MOV R1,R0 Pull R0 ADRL R4,last_fg_gcol TST R0,#128 STREQ R14,[R4] ; bg/fg flag affects last_??_gcol STRNE R14,[R4,#4] MOV R0,R1 B ExitWimp ; set colour using ColourTrans ; in R0 colour value ; bits 0-3 colour index ; bits 4-6 gcol operation ; bit 7 fg/bg int_setcolour Push "R1-R4,LR" AND R3,R0,#2_10000000 ; get the fg/bg flag AND R4,R0,#2_01110000 ; get the gcol mode MOV R4,R4,LSR #4 AND R0,R0,#2_00001111 ; get the logical colour index ; LDR R14,log2bpp CMP R14,#1 ; is this mode monochrome? CMPCC R0,#8 ; and is the colour in the range of 0-7? ORRCC R3,R3,#1:SHL:8 ; if this is so then dither ; LDR R14,ditheringflag ORR R3,R3,R14 ; use dithering if enabled ; BL getpalpointer LDR R0,[R14,R0,LSL #2] ; get the physical colour required ADRL R14,last_fg_gcol TST R3,#128 STREQ R0,[R14] ; bg/fg flag affects last_??_gcol STRNE R0,[R14,#4] Push R0 SWI XColourTrans_SetGCOL Pull R14 ; return palette entry in R14 (New!!!) ; Pull "R1-R4,PC" ;.............................................................................. ; set a foreground colour (checking to see if translation required) foreground EntryS "R0-R4" MOV R3,#&00 MOV R4,#&0 ; fg + GCOL action 0 B settranslate [ TrueIcon1 icon_fg ALTENTRY MOV R3,#&00 MOV R4,#&00 [ TrueIcon2 LDR R0, truefgcolour | LDR R14,truefgcolour ; check for a 24-bit colour override CMP R14,#-1 BEQ settranslate MOV R0,R14 ] B settruecolour ] window_fg ALTENTRY MOV R3,#&00 MOV R4,#&00 ; GCOL action 0 [ TrueIcon3 B settruecolour | LDR R14,[handle,#w_flags] TST R14,#wf_realcolours ; need translation? BNE setnotranslate B settranslate ; call a suitable routine ] ;.............................................................................. ; set a background colour (checking to see if translation required) background ALTENTRY MOV R3,#&80 MOV R4,#&00 ; bg + GCOL action 0 B settranslate [ TrueIcon1 icon_bg ALTENTRY MOV R3,#&80 MOV R4,#&00 [ TrueIcon2 LDR R0, truebgcolour | LDR R14,truebgcolour ; check for a 24-bit colour override CMP R14,#-1 BEQ settranslate MOV R0,R14 ] B settruecolour ] window_bg ALTENTRY MOV R3,#&80 MOV R4,#&00 ; GCOL action 0 [ TrueIcon3 B settruecolour | LDR R14,[handle,#w_flags] TST R14,#wf_realcolours ; need translation? BEQ settranslate ; call suitable routine ; fall through ] ;.............................................................................. ; set the colour performing a suitable translation ; in R0 logical colour in bits 0-3 ; R3 fg / bg bits ; R4 logical operation setnotranslate AND R0,R0,#&F ; assume R0 is a GCOL value SWI XColourTrans_SetColour EXITS settranslate AND R0,R0,#&F ; only 4 bits describe the colour to setup ; LDR R14,log2bpp CMP R14,#1 ; is this mode monochrome? CMPCC R0,#8 ; and is the colour in the range of 0-7? ORRCC R3,R3,#1:SHL:8 ; if this is so then dither ; LDR R14,ditheringflag ORR R3,R3,R14 ; use dithering if CMOS enabled it ; BL getpalpointer LDR R0,[R14,R0,LSL #2] ; get the physical colour required ; SWI XColourTrans_SetGCOL ; and set the colour EXITS [ TrueIcon1 settruecolour [ TrueIcon2 LDR R14, log2bpp TEQ R14, #0 BNE %FT01 Push "R4 - R6" ; in 2-colour modes, dither greys MOV R4, R0, LSR #8 AND R4, R4, #&FF MOV R5, R0, LSR #16 AND R5, R5, #&FF MOV R6, R0, LSR #24 TEQ R4, R5 TEQEQ R5, R6 ORREQ R3, R3, #&100 Pull "R4 - R6" 01 ] LDR R14,ditheringflag ORR R3,R3,R14 ; use dithering if CMOS enabled it ; SWI XColourTrans_SetGCOL ; and set the colour EXITS ] ; ; Adjust the scaling block if required ; ; in R6 -> scaling block ; out [R6] may have been modified ; scaled Push "R8-R11" LDMIA R6,{R8-R11} ; bodge factors if half size TST R1,#if_halfsize MOVNE R10,R10,LSL #1 MOVNE R11,R11,LSL #1 Push "R8-R11" MOV R6,sp BL wimp_SpriteOp ADD sp,sp,#4*4 Pull "R8-R11" Pull "R1,R6-R7,PC" ; ; Plot sprite ; Entry: R1 = icon flag word ; R3,R4 = x,y coords to plot sprite at ; R5 = GCOL action (8) ; [thisCBptr], [lengthflags], [spritename] set up ; wimp_SpriteOp_putsprite Push "R1,R6-R7,LR" ; LDR R7,pixtable_at ; -> translation table ; TST R1,#is_inverted:OR:is_shaded [ PlotSpritesFromPalette BICNE R5,R5,#16 ; ensure we don't use the palette ] BLNE calcinverse ; updates R7 ; LDRB R0,sprite_needsfactors TEQ R0,#0 ; do I need to translate TSTEQ R1,#if_halfsize ; does need factors if half size ; MOVNE R0,#SpriteReason_PutSpriteScaled ADRNE R6,sprite_factors BNE scaled ; MOV R0,#SpriteReason_PutSpriteUserCoords unscaled BL wimp_SpriteOp Pull "R1,R6-R7,PC" ; ; do sprite operation ; [thisCBptr] = version in window defn ; or version in indirected sprite validation string ; [lengthflags] <= 0 ==> [spritename] --> sprite itself, else name ; wimp_SpriteOp Push "R1,R2,R11,LR" LDR R1,thisCBptr ; version for this sprite LDR R2,spritename ; ditto CMP R1,#1 ; 0 ==> use system sprite pool ORRHS R0,R0,#&100 ; 1 ==> use common sprite pool BNE %FT01 11 [ SpritePriority LDR R1,baseofhisprites | LDR R1,baseofsprites ; common sprite pool is split in 2 ] MOV R11,R0 BL do_spriteop ; first try the RAM sprites Pull "R1,R2,R11,PC",VC LDR R14,[R0] TEQ R14,#ErrorNumber_Sprite_DoesntExist ; preserves V MOVEQ R0,R11 [ SpritePriority LDREQ R1,baseoflosprites | LDREQ R1,baseofromsprites ; in resourcefs: ] BLEQ do_spriteop ; then the ROM sprites Pull "R1,R2,R11,PC" 01 MOV R11,R0 ; BL do_spriteop Pull "R1,R2,R11,PC",VC ; LDR R14,[R0] TEQ R14,#ErrorNumber_Sprite_DoesntExist ; preserves V MOVEQ R0,R11 ORREQ R0,R0,#&100 BEQ %BT11 ; Pull "R1,R2,R11,PC" do_spriteop Push "LR" [ true AND R14, R0, #&FF TEQ R14, #SpriteReason_DeleteSprite ; is able to get here, provided it came via *WimpKillSprite LDREQ R14, baseofromsprites TEQEQ R1, R14 Pull "PC", EQ ; don't attempt to delete ROM sprites! ] LDR R14,lengthflags CMP R14,#0 ; if length 0, then R2 --> sprite ANDEQ R0,R0,#&0FF ORREQ R0,R0,#&200 SWI XOS_SpriteOp Pull "PC" ;---------------------------------------------------------- ; calculate new ttr table to deal with inverting the sprite ; Entry: R1 = icon flag word ; R0,R6 = input/output log2bpp <-- don't count on this! ; R7 --> pixtable ; Exit: pixtable updated to allow for inverting/shading ;--------------------------------------------------------- calcinverse ROUT Entry "R0-R7" ADR R7,inversefunc ; pointer to the transfer function MOV R6,R1 LDR R4,pixtable_at TEQ R4,#0 EXIT EQ ; no pixtable! [ true ; BJGA bugfix: was sometimes trying to work from a paged-out sprite! LDR R1, sprite_log2bpp ; if <256-colour sprite without palette, we pass palette from Wimp workspace, so no problem CMP R1, #3 ; if <256-colour sprite with palette, cachespritedata has already updated selecttable_args BLGE cachespriteaddress ; R2 -> this sprite, ie *not* the first sprite in this run of matching-mode sprites! EXIT VS ; bail out now if sprite not found! CMP R1, #3 Push "R2", GE ADR R0, selecttable_args LDMIA R0, {R0-R5} LDRGE R0, baseofsprites ; any non-system sprite area will do Pull "R1", GE | ADR R0,selecttable_args LDMIA R0,{R0-R5} ; get the parameters for the call ] ORR R5,R5,#1:SHL:2 ; mark as a transfer function supplied SWI XColourTrans_GenerateTable ; SWI XColourTrans_InvalidateCache MOV R0,#-1 STR R0,sprite_lastmode STRB R0,sprite_needsfactors ; mark as recache and needing translation table CLRV EXIT ;------------------------------------------------------------------------------ ; Routine called to process the RGB and generate a suitable output RGB based ; on the shading or inversion required. ; ; in R0 physical colour to manipulate ; R12 icon flags to be modified ; out R0 modified RGB value - all other registers preserved ;------------------------------------------------------------------------------ inversefunc EntryS "R1-R4" MOV R4,#&FF ; mask used to extract the various components of the word BIC R0,R0,R4 ; clear out the bottom bits MOV R3,R0,LSR #24 ; extract the blue AND R2,R4,R0,LSR #16 ; extract the green AND R1,R4,R0,LSR #8 ; extract the red Debug inverse,"InverseFunc: red,green,blue",R1,R2,R3 TST R12,#is_inverted ; Inverting? BEQ %FT10 ; No then jump [ UrsulaHighlighting ; New highlighting for Risc PC 2 release [ true MOV R0, R1, LSL#8 ; Convert to 16 bit fixed point ADD R0, R0, #128 MOV R1, R2, LSL#8 ; Convert to 16 bit fixed point ADD R1, R1, #128 MOV R2, R3, LSL#8 ; Convert to 16 bit fixed point ADD R2, R2, #128 SWI XColourTrans_ConvertRGBToHSV ; R0->H, R1->S, R2->V LDR R3, =&FFFF CMP R1, #1:SHL:16 MOVHS R1, R3 CMP R2, #1:SHL:16 MOVHS R2, R3 MUL R4, R1, R2 ; can't use MLA in case of overflow SUB R2, R3, R2 ; V = 1 - V SUB R2, R2, R2, LSR#2 ; V = .25 (3 - 3V) ADD R2, R2, R1, LSR#2 ; V = .25 (3 - 3V + S) ADD R2, R2, R4, LSR#18 ; V = .25 (3 - 3V + S + SV) SWI XColourTrans_ConvertHSVToRGB ; R0->R, R1->G, R2->B CMP R2, #1:SHL:16 MOVLO R3, R2, LSR#8 ; Convert to 8 bit MOVHS R3, #255 CMP R1, #1:SHL:16 MOVLO R2, R1, LSR#8 ; Convert to 8 bit MOVHS R2, #255 CMP R0, #1:SHL:16 MOVLO R1, R0, LSR#8 ; Convert to 8 bit MOVHS R1, #255 | ; Alternative (original) Ursula highlighting scheme TEQ R1,R2 TEQEQ R1,R3 ; grey ? BEQ %FT20 MOV R0,R1,LSL #8 ; Convert to 16 bit fixed point ADD R0,R0,#128 MOV R1,R2,LSL #8 ; Convert to 16 bit fixed point ADD R1,R1,#128 MOV R2,R3,LSL #8 ; Convert to 16 bit fixed point ADD R2,R2,#128 SWI XColourTrans_ConvertRGBToHSV ; R0->H, R1->S, R2->V ADD R0,R0,#180:SHL:16 CMP R0,#360:SHL:16 SUBHI R0,R0,#360:SHL:16 SWI XColourTrans_ConvertHSVToRGB ; Form RGB CMP R2,#1:SHL:16 MOVLO R3,R2, LSR #8 ; Convert to 8 bit MOVHS R3, #255 CMP R1,#1:SHL:16 MOVLO R2,R1, LSR #8 ; Convert to 8 bit MOVHS R2, #255 CMP R0,#1:SHL:16 MOVLO R1,R0, LSR #8 ; Convert to 8 bit MOVHS R1, #255 20 RSB R1,R1,#255 RSB R2,R2,#255 ; make a negative RSB R3,R3,#255 SUB R1,R1,R1,LSR #2 SUB R2,R2,R2,LSR #2 ; darken a little SUB R3,R3,R3,LSR #2 ] | TEQ R1,R2 TEQEQ R1,R3 ; grey ? RSBEQ R1,R1,#255 RSBEQ R2,R2,#255 RSBEQ R3,R3,#255 BEQ %FT10 CMP R1,#5 CMPGT R2,#5 CMPGT R3,#5 ; if one is less than 5, then essentially un saturated MOVLE R1,R1, LSR #1 MOVLE R2,R2, LSR #1 MOVLE R3,R3, LSR #1 BLE %FT10 ; Invert colour MOV R0,R1,LSL #8 ; Convert to 16 bit fixed point ADD R0,R0,#128 MOV R1,R2,LSL #8 ; Convert to 16 bit fixed point ADD R1,R1,#128 MOV R2,R3,LSL #8 ; Convert to 16 bit fixed point ADD R2,R2,#128 SWI XColourTrans_ConvertRGBToHSV ; R0->H, R1->S, R2->V CMP R1,#1:SHL:11 ; S < 1/32? - i.e. gray? RSBLO R2,R2,#1:SHL:16 ; Yes then v = 1 - V MOVHS R4,#10:SHL:12 ; k=10/16 MULHS R3,R2,R4 ; Else V = V*k MOVHS R2,R3,LSR #16 ; v = V*k, adjusting for multiply SWI XColourTrans_ConvertHSVToRGB ; Form RGB CMP R2,#1:SHL:16 MOVLO R3,R2, LSR #8 ; Convert to 8 bit MOVHS R3, #255 CMP R1,#1:SHL:16 MOVLO R2,R1, LSR #8 ; Convert to 8 bit MOVHS R2, #255 CMP R0,#1:SHL:16 MOVLO R1,R0, LSR #8 ; Convert to 8 bit MOVHS R1, #255 ] Debug inverse,"Inverted red,green,blue",R1,R2,R3 10 TST R12,#is_shaded ; Shaded? BEQ %FT20 ; No then jump ; Grey the colour MOV R4,#77 MUL R4,R1,R4 ; red *77 MOV R14,#150 MLA R4,R2,R14,R4 ; red *77 + green *150 RSB R3,R3,R3,LSL #3 ADD R4,R4,R3,LSL #2 ; red *77 + green *150 + green *28 ADD R4,R4,#&7F ; Rounding ADD R4,R4,R4,LSL #8 ; Make 16 bit fractional ADD R4,R4,#&100 ; Rounding MOV R4,R4,LSR #16 ; Convert to 8bit luma MOV R0, #&b0 ; Low point (&b0 - &18), (&b0b0b0 is colour 2) MOV R1, #&ff ; High point (&b0 + &17) MUL R2,R4,R1 ; V*h MUL R3,R4,R0 ; V*l SUB R2,R2,R3 ; V*h - V*l ADD R4,R0,R2,LSR #8 ; V*h - V*l + l normalised => V = V*(h-l) +l MOV R1,R4 MOV R2,R1 MOV R3,R1 ; Map all colours to grey Debug inverse,"Grey to",R1 20 MOV R0,R1,LSL #8 ORR R0,R0,R2,LSL #16 ORR R0,R0,R3,LSL #24 ; recombine to make &BBGGRRxx EXITS ;; --------------------------------------------------------------------------- ;; Miscellaneous routines ;; --------------------------------------------------------------------------- ; ; set up graphics window ; graphicswindow ROUT EntryS "x0,y0,x1,y1,R10" ; CMP x0,#0 MOVLT x0,#0 CMP y0,#0 MOVLT y0,#0 ; ADR R14,clipx0 ; used by drawicon STMIA R14,{x0,y0,x1,y1} ; LDR R10,commandflag ORR R14,R10,#cf_wimpdoingvdu STR R14,commandflag ; SWI XOS_WriteI+24 ; set graphics window Coords x0,y0 SUB x1,x1,#1 SUB y1,y1,#1 Coords x1,y1 ; STR R10,commandflag ; EXITS ; ; clear graphics window ; defaultwindow EntryS "x0,y0,x1,y1,R10" ; LDR R10,commandflag ORR R14,R10,#cf_wimpdoingvdu STR R14,commandflag ; ADR R14,scrx0 LDMIA R14,{x0,y0,x1,y1} ; include icon bar ADR R14,clipx0 STMIA R14,{x0,y0,x1,y1} SWI XOS_WriteI+26 ; STR R10,commandflag ; EXITS ; ; plot a solid rectangle in the background colour ; solidrectangle TEQ x0,x1 ; SMC: don't draw size 0 icons TEQNE y0,y1 MOVEQ PC,LR Push "R1,R2,x1,y1,LR" ; Plot 4,x0,y0 ; plot code &64 is WAAAY slower LDR R14,dx SUB x1,x1,R14 LDR R14,dy SUB y1,y1,R14 Plot &67,x1,y1 ; Pull "R1,R2,x1,y1,PC" ; ; plot a rectangular outline in the foreground colour ; hollowrectangle TEQ x0,x1 ; SMC: don't draw size 0 icons TEQNE y0,y1 MOVEQ PC,LR Push "R1,R2,x1,y1,LR" ; LDR R14,dx SUB x1,x1,R14 LDR R14,dy SUB y1,y1,R14 ; Plot &04,x0,y0 Plot &05,x1,y0 Plot &05,x1,y1 Plot &05,x0,y1 Plot &05,x0,y0 ; Pull "R1,R2,x1,y1,PC" ; ; turn off drag rectangle ; nodrag EntryS "x0,y0,x1,y1" ADR R14,dragx0 LDMIA R14,{x0,y0,x1,y1} LDRB R14,dragflag TEQ R14,#0 MOVNE R14,#0 STRNEB R14,dragflag ; Plot to remove box [ false MOVNE R0,#drg_off BLNE dottedbox1 | BEQ %FT06 [ Autoscr LDR R14, dragflags TST R14, #dragf_clip ; clipped dragboxes must only be redrawn within their own window's visible rectangles MOVNE R0, #drg_off BLNE dottedbox1_clipped ; calls OS_ScreenMode 5 as part of redraw loop BNE %FT06 ] MOV R0, #drg_off BL dottedbox1 [ ChocolateScreen MOV R0, #5 ; ChocolateUpdate reason code SWI XOS_ScreenMode ] 06 ] EXITS ; ; move the drag rectangle to a new position (x0,y0,x1,y1) ; yesdrag EntryS "cx0,cy0,cx1,cy1" ; ADR R14,dragx0 ; Examine the old dragbox LDMIA R14,{cx0,cy0,cx1,cy1} LDRB R14,dragflag CMP R14,#0 BNE %FT01 ; LDR R14,dragtype ; Leading edge CMP R14,#drag_subr_posn BLO yesdr1 B yesdrplot ; Do a plot the first time round (NOT A MOVE !) 01 CMP x0,cx0 ; Dragbox continuing CMPEQ y0,cy0 CMPEQ x1,cx1 CMPEQ y1,cy1 BEQ yesdr2 ; just rotate the dashes if it's keeping the same position ; yesdr1 LDR R14,dragtype ; Dragbox moving CMP R14,#drag_scrollboth CMPNE R14,#drag_subr_posn-1 BLS %FT01 LDR R14,dragsubr_move ; does it have a move routine? AcceptLoosePointer_NegOrZero R14,0 CMP R14,R14,ASR #31 BEQ %FT01 ; ; Plot to translate/resize box - dashes don't rotate here [ Autoscr LDR R14, dragflags TST R14, #dragf_clip ; clipped dragboxes must only be redrawn within their own window's visible rectangles MOVNE R0, #drg_move BLNE dottedbox1_clipped BNE %FT02 ] MOV R0,#drg_move BL dottedbox1 [ ChocolateScreen MOV R0, #5 ; ChocolateUpdate reason code SWI XOS_ScreenMode ] B %FT02 01 ; No move routine - remove and redraw [ false BL nodrag | ; Plot to toggle box [ Autoscr LDR R14, dragflags TST R14, #dragf_clip ; clipped dragboxes must only be redrawn within their own window's visible rectangles BLNE dottedbox_toggle_clipped BNE %FT02 ] BL dottedbox_toggle [ ChocolateScreen MOV R0, #5 ; ChocolateUpdate reason code SWI XOS_ScreenMode ] B %FT02 ] yesdrplot ; Plot to draw box [ Autoscr LDR R14, dragflags TST R14, #dragf_clip ; clipped dragboxes must only be redrawn within their own window's visible rectangles MOVNE R0, #drg_on BLNE dottedbox1_clipped BNE %FT02 ] MOV R0,#drg_on BL dottedbox1 [ ChocolateScreen MOV R0, #5 ; ChocolateUpdate reason code SWI XOS_ScreenMode ] 02 ; Dragbox has now been moved ADR R14,dragx0 STMIA R14,{x0,y0,x1,y1} ; store new coords MOV R14,#1 STRB R14,dragflag EXITS ; yesdr2 ; Plot to rotate dashes, if necessary [ true BL rotdotdash BNE %FT01 ; don't do anything if timer hasn't counted down MOV R0, #drg_move STRB R0, dragaction LDRB R0, dotdash2 [ Autoscr LDR R14, dragflags TST R14, #dragf_clip ; clipped dragboxes must only be redrawn within their own window's visible rectangles BLNE dottedbox_clipped BNE %FT01 ] BL dottedbox [ ChocolateScreen MOV R0, #5 ; ChocolateUpdate reason code SWI XOS_ScreenMode ] 01 | BL rotdotdash MOVEQ R0,#drg_move STREQB R0,dragaction LDREQB R0,dotdash2 BLEQ dottedbox ] EXITS [ Autoscr ; ; force the drag rectangle off/on (if it is enabled) ; forcedrag_off Entry "R0-y1" ; LDRB R14, dragflag CMP R14, #0 EXIT EQ ADR R14, dragx0 LDMIA R14, {x0, y0, x1, y1} [ false ; Some DragASprite callers have a bounding box smaller than the sprite (duh), ; so we can't optimise out dragboxes that don't intersect the graphics window :-( Push "x0, y0, x1, y1" ADR R14, clipx0 LDMIA R14, {cx0, cy0, cx1, cy1} SUBS R0, x1, x0 ADDLT x0, x0, R0 ; ensure right way round SUBLT x1, x1, R0 LDR R0, dx SUB x0, x0, R0 ; add a pixel all round for luck ADD x1, x1, R0 SUBS R0, y1, y0 ADDLT y0, y0, R0 ; ensure right way round SUBLT y1, y1, R0 LDR R0, dy SUB y0, y0, R0 ; add a pixel all round for luck ADD y1, y1, R0 CMP x0, cx0 MOVGT cx0, x0 ; cx0 = max (x0, cx0) CMP x1, cx1 MOVLT cx1, x1 ; cx1 = min (x1, cx1) CMP y0, cy0 MOVGT cy0, y0 ; cy0 = max (y0, cy0) CMP y1, cy1 MOVLT cy1, y1 ; cy1 = min (y1, cy1) CMP cx1, cx0 CMPGT cy1, cy0 Pull "x0, y0, x1, y1" MOVGT R0, #drg_off BLGT dottedbox1 ; don't write back to the drag flag | MOV R0, #drg_off BL dottedbox1 ; don't write back to the drag flag ] ; EXIT forcedrag_on Entry "R0-y1" ; LDRB R14, dragflag CMP R14, #0 EXIT EQ TEQ R14, #2 ; special code => get new dragbox position from tempworkspace ASSERT :INDEX:tempworkspace = 0 ADDEQ R14, wsptr, #4*4 ADRNE R14, dragx0 LDMIA R14, {x0, y0, x1, y1} [ false ; Some DragASprite callers have a bounding box smaller than the sprite (duh), ; so we can't optimise out dragboxes that don't intersect the graphics window :-( Push "x0, y0, x1, y1" ADR R14, clipx0 LDMIA R14, {cx0, cy0, cx1, cy1} SUBS R0, x1, x0 ADDLT x0, x0, R0 ; ensure right way round SUBLT x1, x1, R0 LDR R0, dx SUB x0, x0, R0 ; add a pixel all round for luck ADD x1, x1, R0 SUBS R0, y1, y0 ADDLT y0, y0, R0 ; ensure right way round SUBLT y1, y1, R0 LDR R0, dy SUB y0, y0, R0 ; add a pixel all round for luck ADD y1, y1, R0 CMP x0, cx0 MOVGT cx0, x0 ; cx0 = max (x0, cx0) CMP x1, cx1 MOVLT cx1, x1 ; cx1 = min (x1, cx1) CMP y0, cy0 MOVGT cy0, y0 ; cy0 = max (y0, cy0) CMP y1, cy1 MOVLT cy1, y1 ; cy1 = min (y1, cy1) CMP cx1, cx0 CMPGT cy1, cy0 Pull "x0, y0, x1, y1" MOVGT R0, #drg_on BLGT dottedbox1 ; don't write back to the drag flag | MOV R0, #drg_on BL dottedbox1 ; don't write back to the drag flag ] ; EXIT | ; ; force the drag rectangle off/on (if it is enabled) ; forcedrag_off Push "R0,R1,x0,y0,x1,y1,LR" ; LDRB R14,dragflag CMP R14,#0 ADRNE R14,dragx0 LDMNEIA R14,{x0,y0,x1,y1} MOVNE R0,#drg_off BLNE dottedbox1 ; don't write back to the drag flag ; Pull "R0,R1,x0,y0,x1,y1,PC" forcedrag_on Push "R0,R1,x0,y0,x1,y1,LR" ; LDRB R14,dragflag CMP R14,#0 ADRNE R14,dragx0 LDMNEIA R14,{x0,y0,x1,y1} MOVNE R0,#drg_on BLNE dottedbox1 ; don't write back to the drag flag ; Pull "R0,R1,x0,y0,x1,y1,PC" ] [ Autoscr ; Routines to call dottedbox1 and dottedbox from within an update_window loop ; dottedbox_clipped EntryS "cx0, cy0, cx1, cy1, handle" Debug autoscr, "Called dottedbox_clipped" ADR R1, dottedbox B %FT01 dottedbox_toggle_clipped ALTENTRY Debug autoscr, "Called dottedbox_toggle_clipped" ADR R1, dottedbox_toggle B %FT01 dottedbox1_clipped ALTENTRY Debug autoscr, "Called dottedbox1_clipped" ADR R1, dottedbox1 01 ; initialise window rects for the redraw loop LDR handle, draghandle Abs handle, handle Debug autoscr, "dottedbox(1)_clipped: handle, draghandle =", handle, #draghandle Push "R0, R1, x0, y0, x1, y1" [ true ADD R1, handle, #w_wex0 LDMIA R1, {x0, y0, x1, y1} | ; the below doesn't work for toggle operations ADD R1, handle, #w_wax0 LDMIA R1, {cx0, cy0, cx1, cy1, x0, y0} SUB cx0, cx0, x0 ; get work area x origin SUB cy0, cy1, y0 ; get work area y origin LDMIA sp, {R0, R1, x0, y0} SUB x0, x0, cx0 ; make window-relative SUB y0, y0, cy0 SUB x1, x1, cx0 SUB y1, y1, cy0 SUBS R14, x1, x0 ; is x0 < x1 ? SUBLT x1, x1, R14 ; swap them over if not ADDLT x0, x0, R14 SUBS R14, y1, y0 ; is y0 < y1? SUBLT y1, y1, R14 ; swap them over if not ADDLT y0, y0, R14 LDR R14, dx SUB x0, x0, R14 ; add 1-pixel borders ADD x1, x1, R14 LDR R14, dy SUB y0, y0, R14 ADD y1, y1, R14 ] MOV R0, #getrect_firstrect :OR: getrect_updating :OR: getrect_noicons :OR: getrect_keepdragbox BL int_update_window2 Debug autoscr, "Clipped dragbox redraw: exited int_update_window2" 02 ; redraw loop BL int_get_rectangle Debug autoscr, "Clipped dragbox redraw loop: R0 on exit from int_get_rectangle =", R0 BVS %FT10 TEQ R0, #0 ; finished? BEQ %FT10 LDMIA sp, {R0, R1, x0, y0, x1, y1} MOV R14, PC ; return to PC+8 MOV PC, R1 ; equivalent of BL dottedbox[1] BVC %BT02 10 Pull "R0, R1, x0, y0, x1, y1" EXITS ] ; ; draw a dotted box (similar to hollowrectangle) ; invisible if dragtype=7 or system drag is continuous ; drb_system * (1:SHL:(drag_user-1))-1 drb_user3 * 1:SHL:(drag_user3-1) [ true dottedbox_toggle Push "x0-y1,LR" LDRB R14, dragflag TEQ R14, #0 BEQ %FT01 ; just in case ADR R14, dragx0 LDMIA R14, {x0, y0, x1, y1} MOV R0, #drg_off BL dottedbox1 ; remove old box 01 Pull "x0-y1" MOV R0, #drg_on BL dottedbox1 ; plot new box Pull "PC" ] dottedbox1 STRB R0,dragaction ; R0 = drag action (if subrs used) LDRB R0,dotdash1 dottedbox Push "x1,y1,R10-R12,LR" ; LDR R14,dragtype TEQ R14,#drag_scrollboth MOVEQ R14,#drag_vscroll ; use vscroll bit of sysflags for this LDRB R10,sysflags AND R10,R10,#drb_system ; system drags may be invisible ORR R10,R10,#drb_user3 ; user3 drag is invisible MOVS R10,R10,LSR R14 Pull "x1,y1,R10-R12,PC",CS ; BL setdotdash ; ensure we have the correct pattern ; ; check the drag type to see if we should call a user subroutine ; LDR R14,dragtype Debug ub,"Dragtype",R14 CMP R14,#drag_scrollboth CMPNE R14,#drag_subr_posn-1 BHI callsubr ; Debug ub,"Normal drag",R14 [ true ; make sure OS coordinates don't overflow MOV R14, #&7F00 ; max LDR R0, =-&8000 ; min CMP x0, R14 MOVGT x0, R14 CMP x0, R0 MOVLT x0, R0 CMP y0, R14 MOVGT y0, R14 CMP y0, R0 MOVLT y0, R0 CMP x1, R14 MOVGT x1, R14 CMP x1, R0 MOVLT x1, R0 CMP y1, R14 MOVGT y1, R14 CMP y1, R0 MOVLT y1, R0 ] LDR R14,dx SUB x1,x1,R14 LDR R14,dy SUB y1,y1,R14 ; Push "R1,R2" [ true LDR R0, log2bpp TEQ R0, #0 BEQ %FT01 ; use inverse for 2-colour modes Push "R3, R4" LDR R0, =&80808000 ; mid-grey ensures maximum contrast against all colours MOV R3, #0 MOV R4, #3 SWI XColourTrans_SetGCOL Pull "R3, R4" BVS %FT01 ; use old scheme as fallback Plot &04,x0,y0 Plot &15,x1,y0 ; restart, both endpoints Plot &35,x1,y1 ; continue, omit first point Plot &35,x0,y1 ; continue, omit first point Plot &3D,x0,y0 ; continue, omit both endpoints B %FT02 01 ] Plot &04,x0,y0 Plot &16,x1,y0 ; restart, both endpoints Plot &36,x1,y1 ; continue, omit first point Plot &36,x0,y1 ; continue, omit first point Plot &3E,x0,y0 ; continue, omit both endpoints [ true 02 ] ; Pull "R1,R2,x1,y1,R10-R12,PC" callsubr Debug ub,"User Drag",R14 [ Autoscr Push "cx0, cy0, cx1, cy1, x0, y0" ; must preserve R2-R5 over call now! | Push "x0,y0" ; written back later ] LDRB R8,dragaction ; dragaction = offset from dragwsptr ADR R14,dragwsptr LDR R8,[R14,R8] AcceptLoosePointer_NegOrZero R8,0 CMP R8,R8,ASR #31 ; if null routine, don't call it [ Autoscr ADD R0, sp, #4*4 ; skip cx0 - cy1 on stack LDMIA R0,{R0-R3} ; ALWAYS LOAD THESE !!! | LDMIA sp,{R0-R3} ; ALWAYS LOAD THESE !!! ] ADRNE R14,dragx0 LDMNEIA R14,{R4-R7} LDRNE R12,dragwsptr ; get appropriate workspace pointer MOVNE R14,PC MOVNE PC,R8 [ Autoscr ADD R14, sp, #4*4 ; skip cx0 - cy1 on stack STMIA R14,{R0-R3} ; may have been modified Pull "cx0,cy0,cx1,cy1,x0,y0,x1,y1,R10-R12,PC" | STMIA sp,{R0-R3} ; may have been modified Pull "x0,y0,x1,y1,R10-R12,PC" ] ; ; ensure we have the right dot-dash pattern ; setdotdash Push "R0,R1,LR" ; LDRB R14,dotdash CMP R0,R14 Pull "R0,R1,PC",EQ STRB R0,dotdash ; ORR R1,R0,R0,LSL #8 ORR R1,R1,R1,LSL #16 ; duplicate byte across word LDR R0,=&06170000 ; VDU 23,6 STR R1,[R13,#-4]! STMDB R13!,{R0-R1} ; push onto stack: ADD R0,R13,#2 ; 0,0,23,6,n,n,n,n,n,n,n,n MOV R1,#10 SWI XOS_WriteN ADD R13,R13,#12 Pull "R0,R1,PC" ; ; cycle dot-dash pattern if appropriate ; rotatedefault * 2 ; update on the quarter second rotdotdash Push "R1,LR" SWI XOS_ReadMonotonicTime ; get the current centi-second time LDR R1,rotatecounter SUBS R1,R1,R0 ; should I rotate yet? ADDLE R1,R0,#rotatedefault ; if so then reset the counter for next check STRLE R1,rotatecounter Pull "R1,PC",GT ; balance and then exit; Z=0 (NE) ; LDRB R0,dotdash1 MOVS R0,R0,LSR #1 ORRCS R0,R0,#&80 STRB R0,dotdash1 LDRB R0,dotdash2 MOVS R0,R0,LSR #1 ORRCS R0,R0,#&80 STRB R0,dotdash2 ; TEQ R0,R0 ; set Z flag Pull "R1,PC" ; ; set pointer bounding box (half-open as usual) ; clearpointerwindow ADR x0,scrx0 LDMIA x0,{x0,y0,x1,y1} pointerwindow Push "R0,R1,x1,y1,LR" Debug ptr,"ptrwindow:",x0,y0,x1,y1 SUB x1,x1,#1 SUB y1,y1,#1 ; CMP x0,#-&8000 ; (x0,y1 are normally OK anyway) LDRLE x0,=-&7FFF CMP y0,#-&8000 ; (x0,y1 are normally OK anyway) LDRLE y0,=-&7FFF CMP x1,#&8000 ; keep this signed 16-bit! LDRGE x1,=&7FFF CMP y1,#&8000 ; keep this signed 16-bit! LDRGE y1,=&7FFF ; ADR R1,mouseblk MOV R14,#1 ; reason code 1 STRB R14,[R1,#0] strw x0,R1,1 strw y0,R1,3 strw x1,R1,5 strw y1,R1,7 MOV R0,#&15 SWI XOS_Word ; OSWORD &15 [ NCErrorBox ; If confining the mouse causes it to change position, ; we *don't* want to trigger the reappearance of the pointer ADRL y1, ptrsuspendflag LDR x1, [y1] TEQ x1, #2 ; waiting for a mouse move? Push "R2", EQ ; if so then flush the mouse buffer MOVEQ R0, #21 ; (maybe a bit dodgy, but it's the only way MOVEQ R1, #Buff_Mouse ; to ensure that the next read from the SWIEQ OS_Byte ; mouse buffer was due to the OS_Word call, Pull "R2", EQ ; which doesn't in itself flush the buffer) MOVEQ x1, #1 ; and then flag to ignore the next mouse read STREQ x1, [y1] ] ; Pull "R0,R1,x1,y1,PC" LTORG ;;---------------------------------------------------------------------------- ;; Get_Window_Info - return whole of window data in user's buffer ;;---------------------------------------------------------------------------- ; In R1 bits 2..31 -> window header ; R1 bit 0 set => just copy the header, not the icons ; R1 bit 1 reserved (must be 0) ; userblk = R1 SWIWimp_GetWindowInfo MyEntry "GetWindowInfo" ; BIC userblk,userblk,#3 ; bottom 2 bits are flags LDR handle,[userblk,#u_handle] BL checkhandle_iconbar TST R1,#1 ; bit 0 set => don't return icons BLVC int_get_window_info ; NE => don't return icons B ExitWimp SWIWimp_GetWindowState MyEntry "GetWindowState" LDR handle,[userblk] BL checkhandle_iconbar BLVC int_get_window_state [ ChildWindows BVS ExitWimp LDR R14,openidentifier2 LDR R2,[SP,#1*4] TEQ R2,R14 BNE ExitWimp MOV R14,#0 ; ensure <> "TASK" STR R14,[sp,#1*4] ; R2 on exit = 0 LDR R14,[handle,#w_parent] CMP R14,#nullptr Rel R14,R14,NE STR R14,[SP,#2*4] ; R3 on exit = parent handle LDR R14,[handle,#w_alignflags] STR R14,[SP,#3*4] ; R4 on exit = alignment flags B ExitWimp openidentifier2 DCB "TASK" ; magic word for new form of Wimp_GetWindowState | B ExitWimp ] SWIWimp_GetWindowOutline MyEntry "GetWindowOutline" ; LDR handle,[userblk] BL checkhandle_iconbar ; ADDVC R14,handle,#w_x0 ; get system coordinates LDMVCIA R14,{x0,y0,x1,y1} ADDVC R14,userblk,#u_ow0 STMVCIA R14,{x0,y0,x1,y1} ; B ExitWimp ;----------------------------------------------------------------------------- ; get window info - copy data into the user's buffer ;----------------------------------------------------------------------------- ; In handle -> window info ; userblk -> buffer to receive data ; NE => just return window header ; EQ => return list of icons too ; Out [userblk,#u_ow0..] = window status ; R1,R2,R3 corrupted int_get_window_info MOV R0,#w_size LDREQ R1,[handle,#w_nicons] ; if we need icons, increase size ADDEQ R0,R0,R1,LSL #i_shift MOV R1,#0 ; don't mind about panes B getwindow1 ;.............................................................................. ; In handle -> window info ; userblk -> block to receive data ; Out [userblk,#u_ow0..] = window status ; R1,R2,R3 corrupted int_get_window_state MOV R1,#0 ; don't mind about panes go_get_window_state MOV R0,#w_st1 ; end of status info ; In R0 = number of bytes of data required ; R1 = flags for calc_w_status2 getwindow1 Push LR ; BL calc_w_status2 ; get flags and bhandle (using R1) ; Rel R14,handle Pull "PC",VS STR R14,[userblk,#u_handle] ; ADD R1,userblk,#u_ow0 ; on to window data ADD R2,handle,#w_st0 ; start of status info ; ; Copy the window part ; CMP R0, #w_size ADDLS R3,handle,R0 ADDHI R3,handle,#w_size cplp9 LDR R14,[R2],#4 STR R14,[R1],#4 CMP R2,R3 BCC cplp9 ; ; Copy the icon part if necessary ; SUBS R0,R0,#w_size Pull PC,LS LDR R2,[handle,#w_icons] ADD R3,R2,R0 cplp10 LDR R14,[R2],#4 STR R14,[R1],#4 CMP R2,R3 BCC cplp10 ; Pull PC ;;---------------------------------------------------------------------------- ;; Routines for reading / writing icon states ;;---------------------------------------------------------------------------- SWIWimp_SetIconState MyEntry "SetIconState" ; LDR handle,[userblk] AcceptLoosePointer_Neg handle,-2 CMP handle,#nullptr CMPNE handle,#-2 LDREQ handle,iconbarhandle ; allow access to icon bar BL checkhandle BVS ExitWimp ADD R14,userblk,#4 LDMIA R14,{R0,R1,R2} ; input parameters BL int_set_icon_state B ExitWimp ; ; This routine also does some graphics ; int_set_icon_state Push "R2-R9,LR" ; Debug ic,"Set_Icon_State: icon, EOR, BIC, handle:",R0,R1,R2,handle ; LDR R14,[handle,#w_nicons] CMP R0,R14 BCS exitseticon ; ignore illegal handles ; LDR R14,[handle,#w_icons] ADD R0,R14,R0,ASL #i_shift ; R0 --> icon defn ; LDR R14,[R0,#i_flags] BIC R14,R14,R2 ; clear bits to change EOR R14,R14,R1 ; EOR with new bits STR R14,[R0,#i_flags] ; store new data Debug ic,"Set_Icon_State: new state:",R14 ; LDMIA R0,{x0,y0,x1,y1} Push R14 ; icon flags ; ; now just redraw the icon - if 'funny', get the user to do it ; BL int_update_window ; get rectangle list Pull R14 BVS exitseticon TST R14,#if_funnyicon BNE mustredraw ; [ outlinefont ;I don't think this is necessary (nk) ; LDR R0,systemfont ; TEQ R0,#0 ; TSTNE R14,#if_filled:OR:if_sprite:OR:if_fancyfont ; TSTEQ R14,#if_filled:OR:if_sprite:OR:if_fancyfont ; | ; TST R14,#0 TST R14,#if_filled:OR:if_sprite ; ] BEQ mustredraw ; be careful of inverting ; new for iconbar stuff TST R14,#if_text BEQ uiclp [ BlendedFonts :LAND: RO4 ; any selectable text+sprite icons must be fully redrawn LDR r0,ThreeDFlags TST r0,#ThreeDFlags_NoFontBlending BNE %FT01 AND r0,r14,#if_buttontype TEQ r0,#4 :SHL: ib_buttontype TEQNE r0,#5 :SHL: ib_buttontype TEQNE r0,#7 :SHL: ib_buttontype TEQNE r0,#8 :SHL: ib_buttontype TEQNE r0,#9 :SHL: ib_buttontype TEQNE r0,#10 :SHL: ib_buttontype TEQNE r0,#11 :SHL: ib_buttontype BEQ mustredraw 01 ] [ ThreeDPatch ; if we get to here then it's a text+sprite unfilled icon LDR r0,ThreeDFlags TST r0,#ThreeDFlags_NoIconBgInTransWindows BEQ %FT90 LDRB r0,[handle,#w_wbcol] TEQ r0,#&FF BEQ mustredraw 90 ] LDR R14,iconbarhandle Abs R14,R14 TEQ handle,R14 BEQ mustredraw uiclp BL int_get_rectangle BVS exitseticon TEQ R0,#0 BNE uiclp exitseticon Pull "R2-R9,PC" mustredraw BL markinvalidrects BL losewindowrects B exitseticon ;;---------------------------------------------------------------------------- ;; Get info relating to an icon (coords, flags and name) ;;---------------------------------------------------------------------------- SWIWimp_GetIconState MyEntry "GetIconState" ; LDR handle,[userblk] AcceptLoosePointer_Neg handle,-2 CMP handle,#nullptr CMPNE handle,#-2 LDREQ handle,iconbarhandle ; allow access to icon bar BL checkhandle BVS ExitWimp LDR R0,[userblk,#4] ; icon handle BL int_get_icon_state ; ADD R14,userblk,#8 ; skip window and icon handles STMIA R14!,{x0,y0,x1,y1} STMIA R14,{R1,R2,R3,R4} ; B ExitWimp ; result in R0 ; ; Exit: x0,y0,x1,y1 = coords of icon ; R1 = flags ; R2,R3,R4 = data ; int_get_icon_state Push "LR" ; LDR R2,[handle,#w_nicons] CMP R0,R2 MOVHS R1,#is_deleted ; does not exist! MOVHS R2,#cr ; null name (just in case) Pull "PC",HS LDR R14,[handle,#w_icons] ADD R14,R14,R0,ASL #i_shift LDMIA R14!,{x0,y0,x1,y1} LDMIA R14,{R1,R2,R3,R4} ; Pull "PC" ;;---------------------------------------------------------------------------- ;; Find list of icons satisfying conditions ;; Entry: R0 = window handle ;; userblk --> buffer to contain list (was R1) ;; R2 = bits to consider ;; R3 = desired values in those bits ;; Exit : userblk --> list of matching handles (terminated by -1) ;;---------------------------------------------------------------------------- SWIWimp_WhichIcon MyEntry "WhichIcon" MOV handle,R0 ; R0 < 0 => iconbar BL checkhandle_iconbar BLVC int_which_icon B ExitWimp int_which_icon Push "R4-R7,LR" ; MOV R4,#0 LDR R5,[handle,#w_icons] ADD R5,R5,#i_flags LDR R6,[handle,#w_nicons] MOV R7,userblk whiclp CMP R4,R6 BHS endwhlp AcceptLoosePointer_Neg R0,nullptr2 CMP R0,#nullptr2 ; if iconbar, BNE %FT01 ; check that the task owns this icon Push "R1,R2,R7" BL findicon ; R2 -> iconblock LDREQ R14,[R2,#icb_taskhandle] LDREQ R1,taskhandle TEQEQ R1,R14 Pull "R1,R2,R7" ADDNE R5,R5,#i_size BNE %FT02 01 LDR R14,[R5],#i_size AND R14,R14,R2 ; which bits are interesting TEQ R14,R3 ; what to match with STREQ R4,[R7],#4 ; put in list 02 ADD R4,R4,#1 B whiclp endwhlp MOV R14,#nullptr STR R14,[R7] ; terminator ; Pull "R4-R7,PC" ;;---------------------------------------------------------------------------- ;; Routine to allow the user (and the Wimp!) to drag boxes ;; SWI Wimp_DragBox ;; Entry: R1 =0 or -1 ==> just cancel current drag operation ;; R1 --> block ;; +0 window handle (not used if dragtype >= 5) ;; +4 drag type ;; +8 initial box position (x0,y0,x1,y1) - screen coords ;; +24 parent box (x0,y0,x1,y1) - screen coords ;; if type>7: +40 value to pass to subroutines in R12 (workspace ptr) ;; +44 address of subroutine to call to draw box ;; +48 address of subroutine to call to remove box ;; +52 address of subroutine to call to move box (<=0 ==> can't) ;; - previous box coordinates are supplied ;; - the box may or may not have moved ;; ;; User-supplied subroutines: ;; Entry: SVC mode, ;; R0-R3 = new box coordinates (as derived by mouse movements) ;; R4-R7 = previous box coordinates (undefined unless moving) ;; Exit: R0-R3 = actual box coordinates (normally unchanged) ;; ;;---------------------------------------------------------------------------- ^ 0 dr_handle # 4 dr_type # 4 dr_initbox # 16 dr_parentbox # 16 dr_wsptr # 4 dr_subr_on # 4 dr_subr_off # 4 dr_subr_move # 4 ; if <=0, use undraw/draw sequence SWIWimp_DragBox MyEntry "DragBox" AcceptLoosePointer_NegOrZero userblk,0 CMP userblk,userblk,ASR #31 BLEQ nodragging ; preserves flags BEQ ExitWimp ; =0 or -1 ==> cancel current dragbox ; [ Autoscr LDR R14, openidentifier2 ; watch out for extended API TEQ R2, R14 MOVEQ R14, #0 ; ensure <> "TASK" STREQ R14, [sp, #1*4] ; and store where it will be reloaded into R2 on exit MOVNE R3, #0 ; flags default to 0 if non-extended version of call Push "R3" ; reload into R1 later ] ; LDR handle,[userblk],#4 ; window handle (maybe) LDR R0,[userblk],#4 ; drag type ; CMP R0,#drag_scrollboth CMPNE R0,#drag_subr_posn-1 ADDHI R14,userblk,#dr_wsptr-8 LDMHIIA R14,{R1-R4} ADRHI R14,dragwsptr STMHIIA R14,{R1-R4} ; [ Autoscr RSBS R14, R0, #drag_user CMPLS R0, #drag_scrollboth -1 ; LS => drag type is in range 5 through 11 ; so we need only validate the window handle if dragf_inwind is set SETPSR Z_bit, R14, LS ; now NE => window drag, EQ => drag type 5-11 LDREQ R14, [sp] ; get the new dragflags pushed above TSTEQ R14, #dragf_anchor :OR: dragf_clip ; window-relative bit(s) set => window handle needs validating BLNE checkhandle_iconbar Pull "R1" ; retrieve new dragflags | CMP R0,#drag_scrollboth CMPNE R0,#drag_user-1 BLLE checkhandle_iconbar ; only do this if SYSTEM drag! ] ; LDMVCIA userblk,{cx0,cy0,cx1,cy1,x0,y0,x1,y1} BLVC int_drag_box B ExitWimp ; ; Entry: R0 = drag type ; R1 = flags word (as passed in R0 to extended form of SWI) ; cx0,cy0,cx1,cy1 = initial drag box position ; not used if drag type = 1,2,3,4 or 7 ; x0,y0,x1,y1 = parent box ; handle --> window definition (only if R0<=4) ; [mousexpos] = current mouse x-coordinate ; [mouseypos] = current mouse y-coordinate ; ; Drag types: ; 1 drag window position ; 2 drag window size ; 3 drag horizontal scroll bar ; 4 drag vertical scroll bar ; 5 user drag - box within parent box ; 6 user drag - rubber box with pointer in parent box ; 7 user drag - invisible box with pointer in parent box ; 8 user-supplied subroutine, fixed box within parent ; 9 user-supplied subroutine, rubber box within parent ; 10 user-supplied subroutine, fixed box, disregard buttons ; 11 user-supplied subroutine, rubber box, disregard buttons ; int_drag_box Push "LR" ; if a dragbox starts, cancel any pending double-click state LDR R14,mouseflags TST R14,#mf_wait2clicks BICNE R14,R14,#mf_wait2clicks STRNE R14,mouseflags BLNE doubleptr_off ; only changes ptr if shape = 1 LDR R14,mousexpos STR R14,dragoldx LDR R14,mouseypos STR R14,dragoldy MOV R14,#0 STRB R14,continueflag B %FT01 int_drag_box_continue ; treat mouse as being at last posn Push "R0,LR" LDR R14,dragoldx ; make these coordinates relative LDR R0,dragx1 SUB R14,R14,R0 STR R14,dragoldx LDR R14,dragoldy ; these offsets must be maintained LDR R0,dragy0 SUB R14,R14,R0 STR R14,dragoldy MOV R14,#1 STRB R14,continueflag Pull "R0" 01 ; come here from int_drag_box LDRB R14,continueflag ; don't cancel drag if continuing! CMP R14,#0 BLEQ nodragging ; [ Autoscr LDRNE R1, dragflags ; keep old dragflags if continuing CMP R0, #drag_scrollboth CMPNE R0, #drag_user - 1 BICLS R1, R1, #dragf_anchor :OR: dragf_clip ; window-relative dragging is not applicable to window drags! STR R1, dragflags ; store new dragflags RSBS R14, R0, #drag_user CMPLS R0, #drag_scrollboth -1 SETPSR Z_bit, R14, LS ; NE => window drag, EQ => drag type 5-11 LDREQ R14, dragflags TSTEQ R14, #dragf_anchor :OR: dragf_clip ; now NE => window handle is needed later Rel R14, handle, NE MOVEQ R14, #0 STR R14, draghandle ; ensure handle = 0 if we won't be using it Debug autoscr, "New draghandle =", #draghandle CMP R0, #drag_scrollboth CMPNE R0, #drag_user - 1 | CMP R0,#drag_scrollboth CMPNE R0,#drag_user-1 Rel R14,handle,LS MOVHI R14,#0 STR R14,draghandle ; ensure handle=0 if not window drag ] LDRLE R14,[handle,#w_taskhandle] ; remember who started it! LDRHI R14,taskhandle ; no window assoc. if user drag STR R14,dragtask ; TEQ R0,#drag_posn ; if not moveable, can't drag posn/size TEQNE R0,#drag_size LDREQ R14,[handle,#w_flags] TSTEQ R14,#wf_moveable Pull "PC",EQ ; STR R0,dragtype ; TEQ R0,#drag_user3 ; if no visible box, LDREQ cx0,dragoldx ; box is based on mouse position LDREQ cy0,dragoldy LDREQ cx1,dragoldx ; NB: not suitable for int_drag_box_continue LDREQ cy1,dragoldy ; ; work out initial position of the outline and parent boxes ; TEQ R0,#drag_posn TEQNE R0,#drag_size ADDEQ R14,handle,#w_x0 LDMEQIA R14,{cx0,cy0,cx1,cy1} ; if posn or size, start with outline ; ; calculate offset to theoretical (bodged) coords ; Push "cx0,cy0,cx1,cy1" ; ADDEQ R14,handle,#w_wax0 LDMEQIA R14,{x0,y0,x1,y1} SUBEQ cx0,x0,cx0 ; can corrupt these since set later SUBEQ cy0,y0,cy0 SUBEQ cx1,x1,cx1 SUBEQ cy1,y1,cy1 MOVNE cx0,#0 MOVNE cy0,#0 MOVNE cx1,#0 MOVNE cy1,#0 ADR R14,dragoffx0 STMIA R14,{cx0,cy0,cx1,cy1} ; set up offset to theoretical coords ; Pull "cx0,cy0,cx1,cy1" ; TEQ R0,#drag_hscroll BLEQ draghscrollcoords ; set up cx0,cy0,cx1,cy1,x0,y0,x1,y1 TEQ R0,#drag_vscroll BLEQ dragvscrollcoords ; (ditto) TEQ R0,#drag_scrollboth BLEQ pointeroff BLEQ draghvscrollcoords ; ADR R14,dragx0 STMIA R14,{cx0,cy0,cx1,cy1} ; outline box ; ; if drag_posn, check whether window has wf_nochecks set ; TEQ R0,#drag_posn BNE %FT01 ; [ ChildWindows Push "cx0,cy0,cx1,cy1" LDR cx0,[handle,#w_parent] BL getparentbounds Push "cx0,cy0,cx1,cy1" Pull "x0,y0,x1,y1" Pull "cx0,cy0,cx1,cy1" ; now x0,y0,x1,y1 = bounding box ] LDR R14,[handle,#w_flags] TST R14,#wf_nochecks ; if not bounded, or (parent=-1 and sysflags_nobounds set) [ ChildWindows BNE setpointerbox LDR R14,[handle,#w_parent] CMP R14,#nullptr BNE %FT01 ; restrict if window is bounded and parent <> -1 ] LDREQB R14,sysflags TSTEQ R14,#sysflags_nobounds [ :LNOT: ChildWindows ADR R14,scrx0 LDMIA R14,{x0,y0,x1,y1} ] MOVEQ y0,#sz_scrbot ; exclude icon bar (unless wf_nochecks) BNE setpointerbox ; just ensure pointer is on-screen ; NB: can't do this within int_drag_box_continue 01 ; ; if drag type = drag_size, do more work on the bounding box ; TEQ R0,#drag_size BNE %FT01 ; ADD R14,handle,#w_wax0 LDMIA R14,{cx0,cy0,cx1,cy1} BL minmaxwindow ; x0,y0,x1,y1 = min/max size Pull "PC",VS ADD x0,cx0,x0 ; x0 = wax0 + msx0 SUB R14,cy1,y0 ; y1 = way1 - msy0 ADD x1,cx0,x1 ; x1 = wax0 + msx1 SUB y0,cy1,y1 ; y0 = way1 - msy1 MOV y1,R14 ; avoid propagation ; LDR R14,[handle,#w_x1] ADD x1,x1,R14 SUB x1,x1,cx1 ; x1 = x1 + (w_x1-w_wax1) LDR R14,[handle,#w_y0] ADD y0,y0,R14 SUB y0,y0,cy0 ; y1 = y1 + (w_y0-w_way0) ; LDR R14,[handle,#w_flags] ; if extent is flexible, remove bounds TST R14,#wf_rubbery_wex1 MOVNE x1,#bignum ; later clipped to screen size TST R14,#wf_rubbery_wey0 MOVNE y0,#-bignum ; LDR cx0,[handle,#w_x0] ; restrict window size to screen size LDR cy0,[handle,#w_y1] LDR cx1,scrx1 LDR cy1,scry1 ADD cx0,cx0,cx1 SUB cy0,cy0,cy1 CMP x1,cx0 MOVGT x1,cx0 CMP y0,cy0 MOVLT y0,cy0 ; LDR cx0,[handle,#w_wax1] LDR cy1,[handle,#w_way0] LDR cx1,[handle,#w_x1] ; stop edge going off LDR cy0,[handle,#w_y0] 01 ; ; further clip the parent box to the screen size: ; if WimpFlags bit 5 clear, clip posn and size to screen unless wf_nochecks ; if WimpFlags bit 5 set, clip posn to screen unless wf_nochecks ; [ ChildWindows CMP R0,#drag_size CMPNE R0,#drag_posn LDREQ R14,[handle,#w_parent] ; NB: handle only valid for system drags CMPEQ R14,#nullptr BNE dontclipit ] LDRB R14,sysflags TST R14,#sysflags_offscreen CMPEQ R0,#drag_size CMPNE R0,#drag_posn ; only clip posn drags to screen LDREQ R14,[handle,#w_flags] ; or windows with wf_nochecks set TSTEQ R14,#wf_nochecks LDREQB R14,sysflags TSTEQ R14,#sysflags_nobounds BNE dontclipit ; Push "cx0,cy0,cx1,cy1" ADR R14,scrx0 LDMIA R14,{cx0,cy0,cx1,cy1} max x0,cx0 max y0,#sz_scrbot ; above icon bar min x1,cx1 min y1,cy1 Pull "cx0,cy0,cx1,cy1" dontclipit ; now work out the *pointer* bounding box ; here x0,y0,x1,y1 = parent box ; cx0,cy0,cx1,cy1 = initial position of box itself ; if a drag is continuing, we want to maintain the offset from the mouse position ; to the box, ie. dragoldx-cx1 and dragoldy-cy0 must remain constant LDR R0,dragoldx LDR R1,dragoldy LDRB R14,continueflag TEQ R14,#0 ; if continuing, these are relative to ADDNE R0,R0,cx1 ; bottom-right of box ADDNE R1,R1,cy0 ; ADD x0,x0,R0 SUB x0,x0,cx0 ADD y0,y0,R1 SUB y0,y0,cy0 ADD x1,x1,R0 SUB x1,x1,cx1 ADD y1,y1,R1 SUB y1,y1,cy1 ; STR R0,dragoldx ; ensure initial coords are inside box STR R1,dragoldy ; (forced in by pointerwindow) LDR R14,dx ADD x1,x1,R14 ; we want these coords inclusive LDR R14,dy ADD y1,y1,R14 ; so bodge to avoid decreasing by 1 ; if sysflags_offscreen = 1, allow movement drags to go off bottom-right LDR R0,dragtype ; if dragtype = drag_posn, TEQ R0,#drag_posn [ ChildWindows BNE setpointerbox LDR R14,[handle,#w_parent] CMP R14,#nullptr ] LDREQ R14,[handle,#w_flags] ; and wf_onscreen = 0, TSTEQ R14,#wf_onscreen LDREQB R14,sysflags ; and sysflags_offscreen = 1 ANDEQ R14,R14,#sysflags_offscreen TEQEQ R14,#sysflags_offscreen LDREQ x1,scrx1 ; allow the drag to go off-screen LDREQ y0,scry0 setpointerbox BL pointerwindow ; c.f. graphicswindow ; ; force the rectangle to appear on the screen ; MOV R14,#0 STRB R14,dragflag STRB R14,dotdash ; invalidate current dot-dash ADR R14,dragx0 LDMIA R14,{x0,y0,x1,y1} ; these coords are relevant! BL yesdrag ; Pull "PC" nodragging EntryS "R0-R11" ; LDR R2,dragtype TEQ R2,#drag_scrollboth BLEQ pointeron TEQ R2,#0 BLNE defaultwindow BLNE nodrag ; remove drag box from screen MOVNE R14,#0 ; flags must have been preserved STRNE R14,dragtype STRNE R14,draghandle ; NB: reset drag handle too BLNE clearpointerwindow ; EXITS ;;----------------------------------------------------------------------------- ;; Pointer enabling / disabling routines ;;----------------------------------------------------------------------------- pointeroff EntryS "R0" ADR R0,ptr_off SWI XOS_CLI EXITS ; can't handle errors here pointeron EntryS "R0" ADR R0,ptr_on SWI XOS_CLI EXITS ; can't handle errors here ptr_off DCB "Pointer 0", 0 ptr_on DCB "Pointer", 0 ALIGN ;;---------------------------------------------------------------------------- ;; Routines to check the status of windows etc. ;;---------------------------------------------------------------------------- ;----------------------------------------------------------------------------- ; Get the handle pointer appropriate to the relative one in 'handle' ;----------------------------------------------------------------------------- ; ; checkhandle_owner watches out for illegal access to another task's windows ; this explicitly forbids background processes from accessing their windows ; checkhandle_owner ROUT EntryS "R1" BL checkhandle EXIT VS LDR R14,[handle,#w_taskhandle] LDR R1,polltaskhandle ; NB no-one owns the 'system' windows CMP R1,R14 ; so this check always fails! EXITS EQ MyXError WimpOwnerWindow ; "access to window denied" EXIT MakeErrorBlock WimpOwnerWindow checkhandle_iconbar CMP handle,#-2 LDREQ handle,iconbarhandle ; drop through checkhandle EntryS "R0,R1" ; ; Check the window structure for being inside valid memory ; Abs handle,handle TST handle,#3 BNE errhandle ; If it's not word aligned, it's definitely invalid MOV R0,handle ADD R1,R0,#w_size Debug valid,"WIMP validating: ",r0,r1 SWI XOS_ValidateAddress BVS errhandle BCS errhandle ; ; Check the guard word ; LDR R0,[handle,#w_guardword] LDR R1,=w_guardword_valid CMP R0,R1 ; ; It's clean ; EXITS EQ errhandle Debug err,"**** Task, bad window handle",#taskhandle,handle ; It's dirty MyXError WimpBadHandle STR R0,[sp,#Proc_RegOffset] EXIT MakeErrorBlock WimpBadHandle LTORG ;----------------------------------------------------------------------------- ; calc_w_status - work out window flags (top window) ; Entry: R1 = flag bits (if any set, then ignore window in stack) ;----------------------------------------------------------------------------- calc_w_status ROUT MOV R1,#0 ; default entry sets R1 = 0 calc_w_status2 ; ; This code must be brought up-to-date to deal with child windows ; Note that it no longer affects the ws_open bit - that is set in open/close window ; [ ChildWindows Push "R0,LR" ; ; quick check - if window is not open, clear 'top' bit and set bhandle to -1 ; LDR R0,[handle,#w_flags] MOV R4,#nullptr ; initialise R4 to -1 in any case TST R0,#ws_open BICEQ R0,R0,#ws_top BEQ calcw3 ; ; scan siblings 'above' this one (possibly skipping sibling panes) ; ADD R14,handle,#w_x0 ; bounding box of window LDMIA R14,{x0,y0,x1,y1} ORR R0,R0,#ws_top MOV R3,R1 ; hold 'ignore' flags in R3 [ true ; Scan the windows above us in our own stack; we only want to ignore our *own* panes. ; bhandle needs to be either the window in front of us, or the first non-pane, depending upon R3. ; Backwards in the list sense is higher in the window-stacking sense. LDR R1, [handle, #w_active_link + ll_backwards] lookw1 LDR R2, [R1, #ll_backwards] CMP R2, #nullptr ; have we reached the front of our stack? BEQ lookw2 LDR R14, [R1, #w_flags - w_active_link] TST R14, R3 ; EQ => this window matches our criteria for bhandle CMPEQ R4, #nullptr ; have we already determined bhandle? SUBEQ R4, R1, #w_active_link ; no, so remember bhandle Rel R4, R4, EQ TST R14, #wf_isapane ; we don't want to consider our own panes as stopping us from being on top MOVNE R1, R2 BNE lookw1 lookw2 ; Now we have set up R4, and R1 links the first non-pane window in front of us. ; We're now ready to recurse up the window tree! Push "R4, handle" MOV handle, R0 BL calcw_checkwindow Pull "R4, handle" calcw3 STR R0, [handle, #w_flags] STR R4, [handle, #w_bhandle] TST R0, #ws_open Pull "R0,PC" calcw_checkwindow ; Entry: R0 = window flags of original window ; R1 -> active link in higher window (may actually -> list header if we've reached the front of a stack) ; x0-y1 = bounding box of original window ; handle = window flags of original window, or those of its direct ancestor in this stack ; Exit: R0 has ws_top cleared if R1 window (or any window above it) overlapped original window Entry LDR R2, [R1, #ll_backwards] CMP R2, #nullptr ; are we pointing at the list header? BEQ %FT20 10 Push "handle" SUB handle, R1, #w_active_link BL checkclip ; LT => intersection Pull "handle" BICLT R0, R0, #ws_top ; if we've found an overlapping window, clear "uncovered" bit MOVGE R1, R2 ; otherwise try the next window up BLGE calcw_checkwindow EXIT 20 ; R1 is pointing at the list header, we need to consider the next-highest window stack LDR R1, [R1, #ll_forwards] ; get first window in stack LDR R1, [R1, #w_parent - w_active_link] CMP R1, #nullptr EXIT EQ ; if this was top-level stack, leave bit set and exit (we're uncovered!) LDR R14, [R1, #w_flags] TST R14, #ws_open BICEQ R0, R0, #ws_top ; if parent is closed, children cannot be seen, so clear bit and exit EXIT EQ TST handle, #wf_inborder ADDNE R2, R1, #w_x0 ADDEQ R2, R1, #w_wax0 LDMIA R2, {cx0, cy0, cx1, cy1} ; cx0-cy1 now hold rectangle that original window is clippped to by new ancestor CMP x0, cx0 CMPGE y0, cy0 CMPGE cx1, x1 CMPGE cy1, y1 ; GE => original window isn't clipped by new ancestor BICLT R0, R0, #ws_top EXIT LT ; if clipped, clear bit and exit MOV handle, R14 ; remember the flags for this direct ancestor LDR R1, [R1, #w_active_link + ll_backwards] BL calcw_checkwindow ; and try the new ancestor's higher siblings EXIT | ; Old code that doesn't concern itself with aunts, great-aunts etc., nor clipping by ancestors LDR R2,[handle,#w_active_link+ll_backwards] lookw1 LDR R1,[R2,#ll_backwards] CMP R1,#nullptr BEQ calcw3 LDR R14,[R2,#w_flags-w_active_link] TST R14,R3 CMPEQ R4,#nullptr ; first non-masked window above this one is the bhandle SUBEQ R4,R2,#w_active_link Rel R4,R4,EQ LDR R14,[R2,#w_flags-w_active_link] TST R14,#wf_isapane ; panes never count towards the 'top' bit BNE lookw2 Push "handle" SUB handle,R2,#w_active_link BL checkclip Pull "handle" BICLT R0,R0,#ws_top ; not top if it's covered BLT calcw3 lookw2 MOV R2,R1 B lookw1 calcw3 STR R0,[handle,#w_flags] STR R4,[handle,#w_bhandle] TST R0,#ws_open Pull "R0,PC" ] | Push "R0,LR" ; ; look for this window in the stack ; MOV R3,R1 ; hold 'ignore' flags in R3 LDR R2,activewinds+lh_backwards lookw1 LDR R1,[R2,#ll_backwards] CMP R1,#nullptr MOVEQ R0,#0 BEQ calcw1 SUB R2,R2,#w_active_link TEQ R2,handle MOV R2,R1 BNE lookw1 ; ; store appropriate status in window data ; MOV R0,#ws_open:OR:ws_top ; assume top at this stage calcw1 LDR R14,[handle,#w_flags] BIC R14,R14,#ws_status ORR R14,R14,R0 STR R14,[handle,#w_flags] ; store value so far ; get handle of window above calcw2 ; Is there another window? ; LDR R4,[R2,#ll_backwards] CMP R4,#nullptr ; Passes on as bhandle=nullptr (top) BEQ calcw3 ; ; Is the next window masked out?, if so loop ; LDR R14,[R2,#w_flags-w_active_link] TST R14,R3 MOVNE R2,R4 BNE calcw2 ; next window not masked, convert to bhandle SUB R4,R2,#w_active_link Rel R4,R4 calcw3 STR R4,[handle,#w_bhandle] TST R0,#ws_open Pull "R0,PC",EQ ; window is closed ; ; check whether window is top (ensure nothing (except panes) cover it) ; ADD R0,handle,#w_x0 ; bounding box of window LDMIA R0,{x0,y0,x1,y1} ; lookw2 LDR R1,[R2,#ll_backwards] ; Another window to check? CMP R1,#nullptr Pull "R0,PC",EQ ; Push "handle" ; Convert to handle and step to next SUB handle,R2,#w_active_link MOV R2,R1 LDR R14,[handle,#w_flags] AND R14,R14,#wf_isapane CMP R14,#wf_isapane ; panes don't count BLLT checkclip Pull "handle" ; BGE lookw2 ; ; window is not top - mark status accordingly ; LDR R0,[handle,#w_flags] BIC R0,R0,#ws_top ; not top STR R0,[handle,#w_flags] ; Pull "R0,PC" ] ;------------------------------------------------------------------------------ ; checkclip - see if window indicated by handle intersects x0,y0,x1,y1 ; Exit : LT --> window intersects ;------------------------------------------------------------------------------ checkclip ROUT Push "cx0,cy0,cx1,cy1,LR" ; ADD R14,handle,#w_x0 ; point to outer box of window LDMIA R14,{cx0,cy0,cx1,cy1} ; CMP x0,cx1 ; if x0 < cx1 CMPLT cx0,x1 ; and x1 > cx0 CMPLT y0,cy1 ; and y0 < cy1 CMPLT cy0,y1 ; and y1 > cy0 ; Pull "cx0,cy0,cx1,cy1,PC" ;----------------------------------------------------------------------------- ; routine to work out outer coordinates from x0,y0,x1,y1 and flags ;----------------------------------------------------------------------------- calc_w_x0y0x1y1 ROUT Push "R1,R2,LR" ; LDR R0,[handle,#w_flags] LDRB R14,[handle,#w_tfcol] ; if title fg = 255, TEQ R14,#&FF ; thin borders are not drawn [ ChildWindows LDR R1,dx LDR R2,dy BEQ %FT02 | Pull "R1,R2,PC",EQ ; LDR R1,dx LDR R2,dy ] ; SUB x0,x0,R1 ; line goes outside work area SUB y0,y0,R2 ADD x1,x1,R1 ADD y1,y1,R2 ; ;;<< LDRB R1,xborder ;;<< LDRB R2,yborder [ ChildWindows 01 ] TST R0,#wf_icon3 LDRNE R2,title_height ADDNE y1,y1,R2 ; make room for title TST R0,#wf_icon5 LDRNE R1,vscroll_width ADDNE x1,x1,R1 TST R0,#wf_icon7 LDRNE R2,hscroll_height SUBNE y0,y0,R2 ; Pull "R1,R2,PC" [ ChildWindows 02 TST R0,#wf_icon3 ADDNE y1,y1,R2 ; must add one pixel as well TST R0,#wf_icon5 ADDNE x1,x1,R1 TST R0,#wf_icon7 SUBNE y0,y0,R2 B %BT01 ] ; ; Entry: R0 = icon 'handle' (1-7) ; handle --> window defn ; Exit: x0,y0,x1,y1 = coords of icon ; [ ChildWindows calc_w_iconposn Entry "cx0,cy0,cx1,cy1" BL calc_w_iconposn2 EXIT calc_w_iconposn2 ROUT ; this version returns cx0..cy1 = 'normal' bbox, for scrollbars | calc_w_iconposn ROUT ] EntryS "R1,cx0,cy0,cx1,cy1" ; ChildWindows Debuga x1,"Calc icon posn ",r0 ; ADD R14,handle,#w_x0 LDMIA R14,{cx0,cy0,cx1,cy1} [ ChildWindows LDR R1,[handle,#w_flags] BL calc_w_iconposn_R1 ; calculate from R1 and cx0,cy0,cx1,cy1 (ie. don't look at handle data) ; If there are child window(s) with the wf_inborder bit set, move the scrollbar to make room ; The scrollbar only allows for child windows that are aligned with the left or right of the 'normal' scrollbar position ; NOTE: If you want two windows at the same end, do NOT make them both children of the main parent, as it WILL NOT WORK ; The scrollbar will only budge over if both windows are aligned with the edge of the main parent ; Alternatively make one window a child of the other, or both windows children of a third window (which is a child of the parent). CMP R0,#7 BEQ %FT07 CMP R0,#5 EXITS NE ; move vertical scrollbar to make room for children with wf_inborder set ADD R14,SP,#Proc_RegOffset+4 STMIA R14,{x0,y0,x1,y1} ; cx0,cy0,cx1,cy1 on exit = 'normal' bbox LDR R1,[handle,#w_children + lh_forwards] 01 LDR R14,[R1,#ll_forwards] CMP R14,#nullptr EXITS EQ LDR R14,[R1,#w_flags - w_active_link] TST R14,#wf_inborder BEQ %FT02 ADD R14,R1,#w_x0 - w_active_link LDMIA R14,{cx0,cy0,cx1,cy1} LDR R14,dx SUB R14,x1,R14 CMP cx1,R14 ; if window touches outer edge of v-scroll, BLT %FT02 CMP cx0,x1 CMPLT cy0,y1 CMPLT y0,cy1 ; ignore if completely outside scrollbar range BGE %FT02 LDR R14,dy SUB cy0,cy0,R14 ADD cy1,cy1,R14 CMP cy0,y0 SUBLE y0,cy1,R14,LSL #1 ; move scrollbar upwards if window touches the bottom CMP cy1,y1 ADDGE y1,cy0,R14,LSL #1 ; move scrollbar downwards if window touches the top 02 LDR R1,[R1,#ll_forwards] B %BT01 ; move horizontal scrollbar to make room for children with wf_inborder set 07 ADD R14,SP,#Proc_RegOffset+4 STMIA R14,{x0,y0,x1,y1} ; cx0,cy0,cx1,cy1 on exit = 'normal' bbox LDR R1,[handle,#w_children + lh_forwards] 01 LDR R14,[R1,#ll_forwards] CMP R14,#nullptr EXITS EQ LDR R14,[R1,#w_flags - w_active_link] TST R14,#wf_inborder BEQ %FT02 ADD R14,R1,#w_x0 - w_active_link LDMIA R14,{cx0,cy0,cx1,cy1} LDR R14,dy ADD R14,y0,R14 CMP cy0,R14 ; if window touches bottom of h-scroll, BGT %FT02 CMP y0,cy1 CMPLT cx0,x1 CMPLT x0,cx1 ; ignore if completely outside scrollbar range BGE %FT02 LDR R14,dx SUB cx0,cx0,R14 ADD cx1,cx1,R14 CMP cx0,x0 SUBLE x0,cx1,R14,LSL #1 ; move scrollbar to the right if window touches the left CMP cx1,x1 ADDGE x1,cx0,R14,LSL #1 ; move scrollbar to the left if window touches the right 02 LDR R1,[R1,#ll_forwards] B %BT01 ;............................................................................. ; In R0 = border icon number ; R1 = window flags ; cx0,cy0,cx1,cy1 = outer bounding box of window ; Out x0,y0,x1,y1 = bounding box of border icon (without scrollbar adjustment for wf_inborder child windows) ; R0 preserved, R1,cx0,cy0,cx1,cy1 corrupted calc_w_iconposn_R1 EntryS "R1" ] ; ChildWindows ADRL R14,iconposndata-1 LDRB R14,[R14,R0] ; ;<< LDRB R1,xborder1 ; xborder+dx TST R14,#2_1000 MOVEQ x0,cx0 LDRNE R1,vscroll_width1 SUBNE x0,cx1,R1 TST R14,#2_0010 MOVEQ x1,cx1 ;<< ADDNE x1,cx0,R1 ;<< LDRB R1,yborder1 ; yborder+dy TST R14,#2_0100 MOVEQ y0,cy0 LDRNE R1,title_height1 SUBNE y0,cy1,R1 TST R14,#2_0001 MOVEQ y1,cy1 LDRNE R1,hscroll_height1 ADDNE y1,cy0,R1 [ ChildWindows LDR R1,[SP,#Proc_RegOffset] ; recover window flags from the stack | LDR R1,[handle,#w_flags] ] 01 ADD PC,PC,R0,ASL #2 ; jump ! ; DCD 0 DCD 0 ; extra bodge word cos 1 <= R0 <= 7 ; ASSERT (.-%BT01)=8+4 B check1 ; back B check2 ; close B check3 ; title B check4 ; toggle B check5 ; vscroll B check6 ; resize B check7 ; hscroll [ IconiseButton B check8 ; iconise ] check1 LDR R14,back_width ADD x1,cx0,R14 LDR R14,dx ADD x1,x1,R14 ; EXITS ; ChildWindows check2 LDR R14,close_width ADD x1,cx0,R14 LDR R14,dx ADD x1,x1,R14 ; TST R1,#wf_icon1 LDRNE R14,back_width ADDNE x0,x0,R14 ADDNE x1,x1,R14 ; EXITS ; ChildWindows check3 TST R1,#wf_icon1 LDRNE R14,back_width ADDNE x0,x0,R14 TST R1,#wf_icon2 LDRNE R14,close_width ADDNE x0,x0,R14 [ IconiseButton BEQ %FT01 LDR R14, [handle, #w_parent] CMP R14, #-1 BNE %FT01 LDRB R14, iconisebutton TEQ R14, #0 BEQ %FT01 LDR R14,iconise_width SUB x1,x1,R14 01 ] TST R1,#wf_icon4 LDRNE R14,vscroll_width SUBNE x1,x1,R14 ; EXITS ; ChildWindows check5 TST R1,#wf_icon4:OR:wf_icon3 ; give way to title LDRNE R14,title_height SUBNE y1,y1,R14 TST R1,#wf_icon6:OR:wf_icon7 ; give way to h_scroll LDRNE R14,hscroll_height ADDNE y0,y0,R14 EXITS ; ChildWindows check7 TST R1,#wf_icon6:OR:wf_icon5 LDRNE R14,vscroll_width SUBNE x1,x1,R14 EXITS ; ChildWindows check4 check6 Debug x1," x0 y0 x1 y1 ",x0,y0,x1,y1 EXITS ; ChildWindows [ IconiseButton check8 LDR R14,iconise_width SUB x0,cx1,R14 LDR R14,dx SUB x0,x0,R14 TST R1,#wf_icon4 ; give way to toggle size icon LDRNE R14,vscroll_width SUBNE x0,x0,R14 SUBNE x1,x1,R14 EXITS ] ; ; 2_1000 ==> x0 = cx1-vscroll_width , else cx0 ; 2_0100 ==> y0 = cy1-title_height , else cy0 ; 2_0010 ==> x1 = undefined , else cx1 ; 2_0001 ==> y1 = cy0+hscroll_height, else cy0 ; iconposndata DCB 2_0110 ; back DCB 2_0110 ; quit DCB 2_0100 ; title DCB 2_1100 ; toggle DCB 2_1000 ; v_scroll DCB 2_1001 ; size DCB 2_0001 ; h_scroll [ IconiseButton DCB 2_1100 ; iconise ] ALIGN ;----------------------------------------------------------------------------- ; routine to work out minimum x/y size of a given window ; Entry: handle --> window definition ; Exit : R14 = minimum x/y size ;----------------------------------------------------------------------------- [ ChildWindows title_minwidth * 8 ] minwindowx Push "R0,R1,x1,LR" ; ;<<< LDRB x1,xborder ; used throughout ; LDR R1,[handle,#w_flags] TST R1,#wf_icon3 MOVEQ R14,#0 BEQ minscrx ; check scroll bars ; [ ChildWindows TST R1,#wf_icon1 :OR: wf_icon2 [ true ; BJGA bugfix MOVEQ R14, #0 ; allow title to shrink to zero if no back/quit and minX=1 BEQ %FT01 LDRB R0, [handle, #w_tfcol] TEQ R0, #&FF ; check for borderless windows MOVNE R14, #0 LDREQ R14, dx ; these need an extra pixel to compensate TSTEQ R1, #wf_icon5 MOVEQ R14, R14, LSL #1 ; or two pixels if vscroll is absent too! ADD R14, R14, #title_minwidth 01 | MOVNE R14,#title_minwidth ; min title size if back or quit are present MOVEQ R14,#0 ; allow title to shrink to zero if no back/quit and minX=1 ] LDR R0,[handle,#w_minx] ; word contains x- and y- min MOVS R0,R0,LSL #16 ; if x=0, use title width | LDR R14,[handle,#w_minx] ; word contains x- and y- min MOVS R14,R14,LSL #16 ; if x=0, use title MOVNE R14,#8 ; reasonable size ] BNE ignoretitle ; ignore title if specific ; Push "R1,R2,cx1" LDR R14,[handle,#w_areaCBptr] ; in case title is a sprite STR R14,areaCBptr LDR R1,[handle,#w_titleflags] ADD R2,handle,#w_title BL seticonptrs ; sets up [spritename] etc. ; MOV cx1,#0 ; width of title portion ; TST R1,#if_sprite BEQ %FT01 ASSERT cx1=R4 Push "R3" ; R1 = icon flags BL spritesize ; R3,R4 = sprite size (pixels) MOV cx1,R3 Pull "R3" B %FT02 01 ; 320nk auto title bar width TST R1,#if_text BLNE textwidth 02 LDR R14,dx ADD R14,cx1,R14,ASL #1 ; R14 <- cx1 + 2*dx Pull "R1,R2,cx1" BVS %FT99 ignoretitle TST R1,#wf_icon1 ; back LDRNE x1,back_width ADDNE R14,R14,x1 TST R1,#wf_icon2 ; quit LDRNE x1,close_width ADDNE R14,R14,x1 [ IconiseButton BEQ %FT01 LDR x1, [handle, #w_parent] CMP x1, #-1 BNE %FT01 LDRB x1, iconisebutton TEQ x1, #0 BEQ %FT01 LDR x1,iconise_width ; + iconise ADD R14,R14,x1 01 ] TST R1,#wf_icon5 ; v_scroll BNE %FT01 TST R1,#wf_icon4 ; toggle LDRNE x1,vscroll_width ADDNE R14,R14,x1 01 minscrx TST R1,#wf_icon7 ; h_scroll BEQ gotminx [ ChildWindows LDR R0,[handle,#w_minx] MOV R0,R0,LSL #16 MOVS R0,R0,LSR #16 ; bottom 16 bits are min x MOVNE R0,#0 BNE skiphscroll ; scrollbars can now go to zero size (if minx<>0) ] LDRB R0,scroll_minxbar LDR x1,left_width ADD R0,R0,x1 LDR x1,right_width ADD R0,R0,x1 ; allow for scroll arrows ;<<< ADD R0,R0,x1,LSL #1 ; allow for 2 scroll arrows ; [ hvblip LDR x1,hscroll_blipwidth ADD R0,R0,x1 ] [ ChildWindows skiphscroll ; scrollbar can go to zero width, but we must still consider the size box ] TST R1,#wf_icon5 ; v_scroll BNE %FT02 TST R1,#wf_icon6 ; size LDRNE x1,vscroll_width ADDNE R0,R0,x1 02 CMP R14,R0 ; allow for bottom scroll bar MOVLT R14,R0 gotminx ASSERT (w_minx:AND:3)=0 LDR R1,[handle,#w_minx] ; assume word-aligned MOV R1,R1,LSL #16 MOV R1,R1,LSR #16 ; bottom 16 bits are min x [ ChildWindows CMP R1,#1 MOVEQ R1,#0 ; 1 is a special value (treat as 0 here) ] CMP R14,R1 MOVLT R14,R1 ; take max of the two 99 STRVS R0,[sp] Pull "R0,R1,x1,PC" minwindowy Push "R1,y1,LR" [ ChildWindows LDR R14,[handle,#w_minx] MOVS R14,R14,LSR #16 ; R14 = min y size specified MOVNE R14,#0 ; we can potentially go to zero size if miny=1 LDREQ R14,dy MOVEQ R14,R14,ASL #1 ; back compatibility: R14 <- 2*dy [ I don't know where this came from! ] | ; ;<<< LDRB y1,yborder ; LDR R14,dy MOV R14,R14,ASL #1 ; R14 <- 2*dy ] LDR R1,[handle,#w_flags] TST R1,#wf_icon5 BEQ %FT02 [ ChildWindows LDR y1,[handle,#w_minx] MOVS y1,y1,LSR #16 BNE skipvscroll ; scrollbar can go to zero height if minY > 0 ] LDRB R14,scroll_minybar LDR y1,up_height ADD R14,R14,y1 LDR y1,down_height ADD R14,R14,y1 ; allow for scroll arrows ;<< ADD R14,R14,y1,LSL #1 ; allow for 2 scroll arrows ; [ hvblip LDR y1,vscroll_blipheight ADD R14,R14,y1 ] [ ChildWindows skipvscroll ; we must still consider the size and toggle, even if the scrollbar can go to zero ] TST R1,#wf_icon7 ; if no h_scroll BNE %FT01 TST R1,#wf_icon6 ; and size LDRNE y1,hscroll_height ADDNE R14,R14,y1 01 TST R1,#wf_icon3 ; if no title, BNE %FT02 TST R1,#wf_icon4 ; and toggle LDRNE y1,title_height ADDNE R14,R14,y1 02 ASSERT (w_minx:AND:3)=0 ASSERT w_miny=w_minx+2 LDR R1,[handle,#w_minx] MOV R1,R1,LSR #16 ; R1 = min y size specified [ ChildWindows CMP R1,#1 MOVEQ R1,#0 ; 1 is a special case (treat as 0 here) ] CMP R14,R1 MOVLT R14,R1 ; take max of the two Pull "R1,y1,PC" ;............................................................................. ; In handle -> window definition ; Out x0,y0 = absolute minimum x,y size of window (determined purely by which borders are present) [ ChildWindows minwindow_borders Entry "R1" MOV x0,#0 MOV y0,#0 LDR R1,[handle,#w_flags] TST R1,#wf_icon1 ; back LDRNE x0,back_width TST R1,#wf_icon2 ; quit LDRNE R14,close_width ADDNE x0,x0,R14 TST R1,#wf_icon1 :OR: wf_icon2 TSTNE R1,#wf_icon3 ADDNE x0,x0,#title_minwidth ; title must be this big if back or quit present AND R14,R1,#wf_icon4 :OR: wf_icon5 TEQ R14,#wf_icon4 ; toggle with no v-scroll LDREQ R14,vscroll_width ADDEQ x0,x0,R14 AND R14,R1,#wf_icon5 :OR: wf_icon6 TEQ R14,#wf_icon6 ; size with no v-scroll LDREQ R14,vscroll_width MOVNE R14,#0 max x0,R14 ; see if this is greater than current min x AND R14,R1,#wf_icon3 :OR: wf_icon4 TEQ R14,#wf_icon4 ; toggle with no title LDREQ y0,title_height AND R14,R1,#wf_icon6 :OR: wf_icon7 TEQ R14,#wf_icon6 ; size with no h-scroll LDREQ R14,hscroll_height ADDEQ y0,y0,R14 EXIT ] ;............................................................................. ; In handle -> window definition ; Out x0,y0 = minimum window size ; x1,y1 = maximum window size minmaxwindow Push "LR" ; ADD R14,handle,#w_wex0 LDMIA R14,{x0,y0,x1,y1} SUB x1,x1,x0 SUB y1,y1,y0 BL minwindowx MOVVC x0,R14 BLVC minwindowy MOVVC y0,R14 ; Pull "PC" ; pass back V ;;----------------------------------------------------------------------------- ;; Wimp_SetColourMapping ;; Entry: R1 -> 16 words contining physical entries for Wimp colours / 0 = no translation / -1 = default ;; R2 -> 2 byte transfer table mapping 1BPP sprites to palette above / 0 = current / -1 = default ;; R3 -> 4 byte transfer table mapping 2BPP sprites to palette above / 0 = current / -1 = default ;; R4 -> 16 byte transfer table mapping 4BPP sprites to palette above / 0 = current / -1 = default ;; R5-R7 reserved and must be zero ;;----------------------------------------------------------------------------- SWIWimp_SetColourMapping MyEntry "SetColourMapping" ; Push "R8-R11" CMP R1,#-1 ; = -1 => use default palette table ADREQL R1,emergencypalette STR R1,usephyspaltable ; = 0 => use current palette table CMP R1,#0 ; if table supplied then copy data MOVNE R8,R1 ADRNEL R9,physpaltable LDRNE R10,=?physpaltable ; R10 = number of bytes to copy BLNE set_copyblock ; CMP R2,#0 ; use the default 1BPP mapping table ADREQL R2,transtable1 CMP R2,#-1 ADREQ R2,map1bpp CMP R3,#0 ; use the default 2BPP mapping table ADREQL R3,transtable2 CMP R3,#-1 ADREQ R3,map2bpp CMP R4,#0 ; use the default 4BPP mapping table ADREQL R4,transtable4 CMP R4,#-1 ADREQ R4,map4bpp ; ASSERT ?transtable1= ?map1bpp ASSERT ?transtable2= ?map2bpp ASSERT ?transtable4= ?map4bpp ; ASSERT :INDEX:transtable2 = (:INDEX:transtable1 + ?map1bpp) ASSERT :INDEX:transtable4 = (:INDEX:transtable2 + ?map2bpp) ; Push "R2-R4" ADRL R9,transtable1 ; R9 -> start of transfer area ; Pull "R8" LDR R10,=?transtable1 BL set_copyblock ; copy mapping table for 1BPP Pull "R8" LDR R10,=?transtable2 BL set_copyblock ; copy mapping table for 2BPP Pull "R8" LDR R10,=?transtable4 BL set_copyblock ; copy mapping table for 4BPP ; LDR R2,pixtable_at CMP R2,#0 ; has a pixtable been setup? MOVNE R0,#ModHandReason_Free BLNE XROS_Module ; attempt to release - ignore errors MOV R2,#0 STR R2,pixtable_at ; mark the pixtable as being zapped! MOV R2,#-1 ; and the PixTrans mode STR R2,sprite_lastmode ; LDR R2,tpixtable_at CMP R2,#0 ; has a tool pixtable been setup? MOVNE R0,#ModHandReason_Free BLNE XROS_Module ; attempt to release - ignore errors MOV R2,#0 STR R2,tpixtable_at ; mark the tool pixtable as being zapped! MOV R2,#-1 ; and the tool PixTrans mode STR R2,tsprite_lastmode ; STRB R2,tsprite_needsregen ; re-calcuate border based information ; LDR R2,log2bpp ; is it <8BPP? CMP R2,#3 MOVLT cx0,#-bignum ; force a redraw of the screen MOVLT cy0,#-bignum MOVLT cx1,#bignum MOVLT cy1,#bignum BLLT markinvalid_cx0cy0cx1cy1 ; Pull "R8-R11" ; preserve 'em B ExitWimp ; in R8 -> source data ; R9 -> destination block ; R10 = number of bytes to be copied ; out R8,R9 updated ; R10 =-1 ; R11 corrupt set_copyblock SUBS R10,R10,#1 ; any more bytes left? LDRPLB R11,[R8],#1 STRPLB R11,[R9],#1 ; yup ... so copy it away BPL set_copyblock MOV PC,LR ;.............................................................................. ; mapping tables - real colour to wimp colour map1bpp = 0,7 map2bpp = 0,2,5,7 map4bpp = 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 ALIGN ASSERT ?map1bpp = 2 ASSERT ?map2bpp = 4 ASSERT ?map4bpp = 16 ;;----------------------------------------------------------------------------- ;; Initialise the handling of physical mapping tables etc... ;; NB: corrupts R0-R3 ;;----------------------------------------------------------------------------- initphyspalmap ROUT MOV R0,#0 STR R0,usephyspaltable ; don't indirect to seperate wimp palette ASSERT ?transtable1= ?map1bpp ASSERT ?transtable2= ?map2bpp ASSERT ?transtable4= ?map4bpp ASSERT :INDEX:transtable2 = (:INDEX:transtable1 + ?map1bpp) ASSERT :INDEX:transtable4 = (:INDEX:transtable2 + ?map2bpp) ADRL R0,transtable1 ; R0 -> transtable block ADR R1,map1bpp ; R1 -> table to copy MOV R2,#(?transtable1 +?transtable2 +?transtable4) 00 LDRB R3,[R1],#1 STRB R3,[R0],#1 SUBS R2,R2,#1 BNE %BT00 ; loop back copying default tables for mapping Wimp colours MOV PC,LR ;;----------------------------------------------------------------------------- ;; Return a pointer to the real physical palette ;; out R14 -> palette table to be used ;;----------------------------------------------------------------------------- getpalpointer ROUT Push "R14" LDR R14,usephyspaltable ; indirected palette? TEQ R14,#0 ADREQL R14,paltable ; R14 -> standard palette ADRNEL R14,physpaltable ; R14 -> remapped palette Pull "PC" ;--------------------------------------------------------------------------- ; Push font string. Scans an icon string and determines if it must be copied ; in order to be painted successfully. This is so if (a) the string contains ; any symbol font characters; (b) if it is terminated by a control code ; other than 0, 10, 13 (font manager terminators); (c) if it needs a ; replacement character (validation 'D' command). The copy is made on the ; stack, if necessary. ; ; Now always copies, prepending Font_ComandFont, <start font> ; ; in R1 = flags for icon ; R2 -> string to paint ; R3 = handle for icon font ; R7 -> control sequence list (-1 indicates no list) ; R9 = number of characters to include, iff is_deleted is set in R1 ; out R1 -> string to use ; R7 = difference in stack (*word aligned*) ; all others preserved ; ; R7 on entry points to a list of control sequences that need inserting into ; the pushed font string. The list has the following form: ; +0 = byte index into original string where sequence is to be inserted ; these must be kept in ascending order ; +4 = number of bytes in sequence ; +8 = bytes to insert (eg colour change), padded to next word boundary ; The sequence is terminated by the word -1. The list may need to be writeable. ;--------------------------------------------------------------------------- State_CurrentFont * 0 State_IconFont * 1 State_SymbolFont * 2 pushfontstring TraceL font [ UTF8 Push "R0, R2-R6, R8-R11, LR" | Push "R0, R2-R6, R8-R10, LR" ] [ :LNOT:No32bitCode MRS LR, CPSR Push LR ] Debug err, "pushfontstring: flags=",R1 DebugS err, " string=",R2 Debug err, " handle=",R3 ; R1 = flags for icon ; R2 -> string to paint ; R3 = handle for icon font TraceK font, "pushfontstring: painting " TraceS font, R2 TraceK font, ", flags " TraceX font, R1 TraceK font, ", icon font " TraceX font, R3 TraceNL font [ CnP CMP R7, #nullptr ADREQL R7, null_control_sequence_list STR R7, font_cs_list ] [ UTF8 ; Initialise R11 (flag word, containing list of characters that need mapping to WimpSymbol) BL read_current_alphabet LDR R14, systemfont TEQ R3, R14 ; is it a desktop font icon? LDREQ R11, systemfont_wimpsymbol_map ; get the cached map if so (speedup) MOVNE R11, #0 ; else mark as not yet calculated (may be set during test_arrow) ] MOV R8, R2 ; 323nk allow variable length strings, uses is_deleted flag => r9 valid TST R1,#is_deleted MOVNE R10,#0 ; no replacement character BNE pushfontstring_scan_string MOV R7, R3 ; R8 -> string to paint ; R7 = handle for icon font ;find the replacement character by looking at the validation string MOV R10, #:CHR: 0 LDR R3, validationstring AcceptLoosePointer_NegOrZero R3,-1 CMP R3, R3, ASR #31 BEQ %FT01 ;R3 <= 0 => no validation string MOV R2, #WimpValidation_Display ; R2 = WimpValidation_Display ('D') ; R3 -> validation string BL findcommand [ UTF8 BLEQ checkvalid_getchar TEQ R10, #"\\" ADDEQ R3, R3, R9 BLEQ checkvalid_getchar | LDREQB R10, [R3], #1 TEQEQ R10, #"\\" LDREQB R10, [R3] ] ; R10 = replacement character, or 0 01 MOV R3, R7 ; R3 = handle for icon font ;if the string is not indirected, we stop after 12 characters TST R1, #if_indirected MOVEQ R9, #12 MOVNE R9, #bignum ; R9 = maximum length of string [ UTF8 TEQ R10, #0 BEQ pushfontstring_scan_string LDRB R14, alphabet TEQ R14, #ISOAlphabet_UTF8 BEQ pushfontstring_scan_UTF8_string ; special code for passworded UTF-8 sequences ] pushfontstring_scan_string TraceL font MOV R0, #0 MOV R1, #State_CurrentFont [ UTF8 LDRB R2, alphabet ] MOV R6, #0 ; R0 = index into destination ; R1 = state ; R2 = alphabet ; R3 = handle of icon font ; R6 = index into source ; R8 -> source ; R9 = "source buffer length" (bignum if indirected, else 12) ; R10 = replacement character ; R11 = WimpSymbol map B pushfontstring_end_scan_loop pushfontstring_start_scan_loop ; R4 = width of current character ; R5 = current character TEQ R1, #State_SymbolFont BEQ pushfontstring_scanning_symbol_font TEQ R1, #State_CurrentFont BEQ pushfontstring_scanning_current_font pushfontstring_scanning_icon_font [ UTF8 Push "R9" MOV R9, R5 BL test_arrow Pull "R9" | TEST_ARROW R5 ] ADDEQ R0, R0, #2 MOVEQ R1, #State_SymbolFont B pushfontstring_reinitialise_scan_loop pushfontstring_scanning_current_font [ UTF8 Push "R9" MOV R9, R5 BL test_arrow Pull "R9" | TEST_ARROW R5 ] ADD R0, R0, #2 MOVEQ R1, #State_SymbolFont MOVNE R1, #State_IconFont B pushfontstring_reinitialise_scan_loop pushfontstring_scanning_symbol_font [ UTF8 Push "R9" MOV R9, R5 BL test_arrow Pull "R9" | TEST_ARROW R5 ] ADDNE R0, R0, #2 MOVNE R1, #State_IconFont pushfontstring_reinitialise_scan_loop [ UTF8 ADD R0, R0, R4 ADD R6, R6, R4 TEQ R5, #' ' ADDEQ R0, R0, #1 ; may need expanding to UTF-8 &C2 &A0 in fixupfontstring | ADD R0, R0, #1 ADD R6, R6, #1 ] pushfontstring_end_scan_loop CMP R6, R9 BHS pushfontstring_scan_loop_done [ UTF8 LDRB R5, [R8, R6] ; get byte MOV R4, #1 TEQ R2, #ISOAlphabet_UTF8 TEQEQ R5, #&E2 ; optimisation: unless first byte is &E2 (as with all WimpSymbol characters), Push "R6", EQ ; treat as a byte stream, even if alphabet is UTF-8 ADDEQ R6, R8, R6 MOVEQ R4, #6 BLEQ convert_UTF8_to_UCS4 MOVEQ R5, R6 Pull "R6", EQ ; keep R4 returned from convert routine CMP R5, #" " BHS pushfontstring_start_scan_loop ; must use unsigned in order to handle malformed characters! | LDRB R5, [R8, R6] CMP R5, #" " BHS pushfontstring_start_scan_loop ] pushfontstring_scan_loop_done ; R6 = length of source ;if we did anything at all, switch back to the current font TEQ R1, #State_CurrentFont ADDNE R0, R0, #2 ; R0 = length of destination pushfontstring_switch ;do we need to copy the string? TEQ R10, #:CHR: 0 BNE pushfontstring_use_replacement_string pushfontstring_copy_string TraceL font ;R7 := ALIGN (R0 + 1) ADD R7, R0, #4 [ CnP BL add_control_sequences_to_length ] BIC R7, R7, #3 SUB SP, SP, R7 MOV R1, SP [ AllowMatrix Push "R2-R3" LDR R3, validationstring AcceptLoosePointer_NegOrZero R3,-1 CMP R3, R3, ASR #31 BEQ %FT05 MOV R2, #"M" BL findcommand BNE %FT05 LDRB R14,[R3] Pull "R2-R3" SUB SP,SP,#28 Push "R2-R3" ADD R7,R7,#28 Push "R0-R7" SUB R14,R14,#"0" CMP R14,#9 MOVGT R14,#0 CMP R14,#0 MOVLT R14,#0 ADRL R7,font_matrix ADD R7,R7, R14, LSL #5 ADD R14,SP,#40 LDMIA R7,{R0-R6} STMIA R14,{R0-R6} Pull "R0-R7" 05 Pull "R2-R3" ] MOV R0, #0 MOV R4, #0 MOV R5, #State_CurrentFont ; R0 = index into destination ; R1 -> destination ; R2 = alphabet ; R3 = handle of icon font ; R4 = index into source ; R5 = state ; R6 = maximum index into source (either index of terminator, or max length of buffer) ; R7 = stack alignment ; R8 -> source ; R11 = WimpSymbol map B pushfontstring_end_copy_loop pushfontstring_start_copy_loop [ CnP LDR R9, font_cs_list LDR R10, [R9, #0] ; check to see if we need to insert a control sequence TEQ R10, R4 BNE %FT02 LDR R10, [R9, #4] ; byte count ADD R9, R9, #8 01 LDRB R14, [R9], #1 ; copy control bytes STRB R14, [R1, R0] ADD R0, R0, #1 SUBS R10, R10, #1 BNE %BT01 ADD R9, R9, #3 ; align, and store back in font_cs_list BIC R9, R9, #3 STR R9, font_cs_list 02 ] [ UTF8 LDRB R9, [R8, R4] ; get byte MOV R10, #1 TEQ R2, #ISOAlphabet_UTF8 TEQEQ R9, #&E2 ; optimisation: unless first byte is &E2 (as with all WimpSymbol characters), Push "R4,R6", EQ ; treat as a byte stream, even if alphabet is UTF-8 ADDEQ R6, R8, R4 MOVEQ R4, #6 BLEQ convert_UTF8_to_UCS4 MOVEQ R9, R6 MOVEQ R10, R4 Pull "R4,R6", EQ ; R10 = width of current character ; R9 = current character ] TEQ R5, #State_SymbolFont BEQ pushfontstring_copying_symbol_font TEQ R5, #State_CurrentFont BEQ pushfontstring_copying_current_font pushfontstring_copying_icon_font [ UTF8 BL test_arrow | ;R9 := current character LDRB R9, [R8, R4] TEST_ARROW R9 ] BNE pushfontstring_reinitialise_copy_loop ;append Font_CommandFont and the handle for symbol font [ outlinefont MOV R9, #26 STRB R9, [R1, R0] ADD R0, R0, #1 LDR R9, symbolfont STRB R9, [R1, R0] ADD R0, R0, #1 ;set new state MOV R5, #State_SymbolFont ] B pushfontstring_reinitialise_copy_loop pushfontstring_copying_symbol_font [ UTF8 BL test_arrow | ;R9 := current character LDRB R9, [R8, R4] TEST_ARROW R9 ] BEQ pushfontstring_reinitialise_copy_loop ;append Font_CommandFont and the handle for the icon font MOV R9, #26 STRB R9, [R1, R0] ADD R0, R0, #1 STRB R3, [R1, R0] ADD R0, R0, #1 ;set new state MOV R5, #State_IconFont B pushfontstring_reinitialise_copy_loop pushfontstring_copying_current_font [ outlinefont [ UTF8 BL test_arrow | ;R9 := current character LDRB R9, [R8, R4] TEST_ARROW R9 ] ;append Font_CommandFont and the handle for the appropriate font MOV R9, #26 STRB R9, [R1, R0] ADD R0, R0, #1 MOVNE R9, R3 LDREQ R9, symbolfont STRB R9, [R1, R0] ADD R0, R0, #1 ;set new state MOVNE R5, #State_IconFont MOVEQ R5, #State_SymbolFont ] pushfontstring_reinitialise_copy_loop ;copy a byte LDRB R9, [R8, R4] STRB R9, [R1, R0] ;update both indexes ADD R0, R0, #1 ADD R4, R4, #1 [ UTF8 SUBS R10, R10, #1 BNE pushfontstring_reinitialise_copy_loop ; copy the other bytes in the character! ] pushfontstring_end_copy_loop CMP R4, R6 BLO pushfontstring_start_copy_loop pushfontstring_copy_loop_done ;terminate the destination MOV R9, #:CHR: 0 STRB R9, [R1, R0] ; R0 = length of destination (same as before) B pushfontstring_exit pushfontstring_use_replacement_string TraceL font ;R7 := Align (R6 + 4 + 1) ADD R7, R6, #8 [ CnP BL add_control_sequences_to_length ] BIC R7, R7, #3 SUB SP, SP, R7 MOV R1, SP ; R1 -> destination MOV R0, #0 ; R0 = index into destination ;change to icon font MOV R9, #26 STRB R9, [R1, R0] ADD R0, R0, #1 STRB R3, [R1, R0] ADD R0, R0, #1 MOV R2, #0 ; R2 = counter for source [ CnP LDR R9, font_cs_list LDR R11, [R9, #0] pushfontstring_replacement_loop TEQ R11, R2 ; check if we need to insert a control sequence BNE %FT02 LDR R11, [R9, #4] ADD R9, R9, #8 01 LDRB R14, [R9], #1 ; copy control bytes STRB R14, [R1, R0] ADD R0, R0, #1 SUBS R11, R11, #1 BNE %BT01 ADD R9, R9, #3 ; align BIC R9, R9, #3 LDR R11, [R9, #0] 02 | pushfontstring_replacement_loop ] TEQ R2, R6 ;store replacement character STRNEB R10, [R1, R0] ADDNE R0, R0, #1 ADDNE R2, R2, #1 BNE pushfontstring_replacement_loop ;terminate the string MOV R9, #:CHR: 0 STRB R9, [R1, R0] ; R0 = length of destination [ UTF8 B pushfontstring_exit ] [ UTF8 pushfontstring_scan_UTF8_string ; R3 = handle for icon font ; R8 -> source string ; R9 = maximum byte-count of source string ; R10 = UCS-4 replacement character MOV R0, #0 ; character count MOV R2, R8 ; rover MOV R6, R9 ADD R7, R8, R9 ; -> byte after end of source [ CnP LDR R11, font_cs_list ; -> control sequence list 01 LDR R14, [R11, #0] ; is there a control sequence at this byte offset? SUB R4, R2, R8 ; convert back to offset CMP R4, R14 STRHS R0, [R11, #0] ; if so, then store *character* offset back into list LDRHS R14, [R11, #4] ; and advance to next item ADDHS R11, R11, R14 ADDHS R11, R11, #8 + 3 BICHS R11, R11, #3 | 01 ] MOV R4, R2 BL skipcharR CMP R2, R4 BEQ %FT02 ; break from loop if we've not advanced ADD R0, R0, #1 SUBS R6, R7, R2 ; calculate number of bytes left BHI %BT01 02 ; R0 = number of characters SUB sp, sp, #8 ; we need some scratch space - tempworkspace may already be in use MOV R5, sp MOV R6, R10 BL convert_UCS4_to_UTF8 ADD sp, sp, #8 ; R4 = number of bytes per replacement character MUL R7, R4, R0 [ CnP BL add_control_sequences_to_length ] ADD R7, R7, #3 + 3 BIC R7, R7, #3 ; R7 = Align (R0 + 2 + 1) SUB sp, sp, R7 MOV R1, sp ; R1 -> destination string SUB sp, sp, #8 ; this time, we're using it to hold byte-sequence template MOV R5, sp MOV R6, R10 BL convert_UCS4_to_UTF8 MOV R2, #0 ; character count into destination [ CnP LDR R11, font_cs_list ; -> control sequence list ] ; first, select font: MOV R14, #26 STRB R14, [R1], #1 STRB R3, [R1], #1 ; now put in characters: 01 CMP R2, R0 ; finished? BPL %FT03 [ CnP LDR R14, [R11, #0] ; is there a control sequence at this character offset? TEQ R2, R14 BNE %FT12 LDR R5, [R11, #4] ; byte count ADD R11, R11, #8 11 LDRB R14, [R11], #1 ; copy control bytes STRB R14, [R1], #1 SUBS R5, R5, #1 BNE %BT11 ADD R11, R11, #3 ; align BIC R11, R11, #3 12 ] MOV R5, #0 ; initialise index into replacement character 02 LDRB R14, [sp, R5] STRB R14, [R1], #1 ; copy across byte ADD R5, R5, #1 CMP R5, R4 BLO %BT02 ADD R2, R2, #1 ; increment character count B %BT01 03 ADD sp, sp, #8 ; realign stack ; finally, terminate the string MOV R14, #0 STRB R14, [R1] ; Reset R1 to start of string MOV R1, sp ; Drop through... ] pushfontstring_exit ;get registers back from where we put them ; 320nk Neil Kelleher 22nd Feb 1993 ; This was a thoroughly ghastly bit of code that meant interrupts could ; seriously screw up the painted string. DON'T alter my changes unless ; you understand why i did them, or ASK me! ; ADD SP, SP, R7 MOV LR,SP ADD LR,LR,R7 TEQ R7, #0 [ UTF8 [ No32bitCode ADDNE R7, R7, #4*11 ;11 = no of registers stacked LDMFD LR, {R0, R2, R3, R4, R5, R6, R8, R9, R10, R11, LR} | ADDNE R7, R7, #4*12 ;12 = no of registers stacked LDR R1, [LR] LDMED LR, {R0, R2, R3, R4, R5, R6, R8, R9, R10, R11, LR} ] | [ No32bitCode ADDNE R7, R7, #4*10 ;10 = no of registers stacked LDMFD LR, {R0, R2, R3, R4, R5, R6, R8, R9, R10, LR} | ADDNE R7, R7, #4*11 ;11 = no of registers stacked LDR R1, [LR] LDMED LR, {R0, R2, R3, R4, R5, R6, R8, R9, R10, LR} ] ] ;SP now as at entry. Move it back over the string ; SUB SP, SP, R7 ; R1 -> string to use ; R7 = difference in stack (*word aligned*) [ No32bitCode MOV R1,SP | MSR CPSR_f, R1 MOV R1,SP ] TraceK font, "pushfontstring: using " TraceS font, R1 TraceK font, " stack moved by " TraceD font, R7 TraceK font, " bytes" TraceNL font ;return [ No32bitCode MOVS PC, LR | MOV PC, LR ] [ outlinefont remembercurrentfont TraceL font ;Make sure we know the current font and colours Push "R0-R3, LR" LDR LR, currentfont TEQ LR, #0 Pull "R0-R3, PC", NE SWI XFont_CurrentFont BVS %FT01 CLRV Pull "R0-R3, PC" 01 ;save the current font handle in a safe place STR R0, currentfont STR R1, currentbg STR R2, currentfg STR R3, currentoffset Trace font, "remembercurrentfont: currentfont ", X, R0 ; NK 349 MOV R0,#0 MOV R1,#0 SWI XFont_SwitchOutputToBuffer CLRV Pull "R0-R3, PC" ] [ CnP null_control_sequence_list DCD -1 add_control_sequences_to_length ; On exit, R7 is incremented by the total of the control sequence lengths indicated in font_cs_list Entry "R0" LDR R0, font_cs_list 01 LDR R14, [R0, #0] CMP R14, #nullptr EXIT EQ LDR R14, [R0, #4] ADD R7, R7, R14 ADD R0, R0, R14 ADD R0, R0, #8 + 3 BIC R0, R0, #3 B %BT01 ] [ AllowMatrix font_matrix ; italic DCD 28 DCD 65536,0,13930,65536,0,0 DCD 0 ; larger DCD 28 DCD 71000,0,0,71000,0,0 DCD 0 ; larger still DCD 28 DCD 76500,0,0,76500,0,0 DCD 0 ; larger still and italic DCD 28 DCD 76500,0,19000,76500,0,0 DCD 0 ; reverse italic DCD 28 DCD 65536,0,-13930,65536,0,0 DCD 0 ; larger still DCD 28 DCD 131072,0,0,131072,0,0 DCD 0 ; narrow DCD 28 DCD 52000,0,0,65536,0,0 DCD 0 ; tiny DCD 28 DCD 32768,0,0,32768,0,0 DCD 0 ] [ UTF8 ; This table cunningly works both as character strings and character numbers wimpsymbols DCD &00000080 ; tick/euro DCD &00000084 ; cross DCD &00000088 ; left arrow DCD &00000089 ; right arrow DCD &0000008A ; down arrow DCD &0000008B ; up arrow ; The next two tables *must* be kept in the same order! wimpsymbols_UTF8 DCD &00949CE2 ; tick/euro DCD &00989CE2 ; cross DCD &009087E2 ; left arrow DCD &009287E2 ; right arrow DCD &009387E2 ; down arrow DCD &009187E2 ; up arrow wimpsymbols_UCS4 DCD &00002714 ; tick/euro DCD &00002718 ; cross DCD &000021D0 ; left arrow DCD &000021D2 ; right arrow DCD &000021D3 ; down arrow DCD &000021D1 ; up arrow ; Work out which characters need mapping to WimpSymbol in this font ; Entry: R3 = font handle ; Exit: R11 contains bits, bit n *clear* means index-n character in wimpsymbols table needs mapping measure_symbols Entry "R0-R8" MOV R11, #-1 ; start off assuming no glyphs need mapping LDRB R14, alphabet TEQ R14, #ISOAlphabet_UTF8 ADRNE R7, wimpsymbols ADREQ R7, wimpsymbols_UTF8 MOV R8, #0 ; index into symbol list MOV R0, R3 01 SUB sp, sp, #16 ; space for returned bbox block MOV R1, #-1 Push "R1" ; no split character MOV R1, #0 Push "R1" ; no offsets Push "R1" Push "R1" Push "R1" ADD R1, R7, R8, LSL#2 LDR R2, = 1:SHL:18 :OR: 1:SHL:8 :OR: 1:SHL:5 MOV R3, #bignum MOV R4, #bignum MOV R5, sp SWI XFont_ScanString ADD sp, sp, #20 Pull "R1-R2,R5-R6" ; load bounding box from stack SUBS R5, R5, R1 ; calc bbox width/height SUBLES R6, R6, R2 SETPSR Z_bit, R14, LE TEQEQ R3, #0 TEQEQ R4, #0 ; now EQ => offsets are both zero, and bbox has zero or negative width and height MOVEQ R14, #1 BICEQ R11, R11, R14, LSL R8 ; if character is *not* defined, then clear its bit in R11 (=> test_arrow returns EQ) ADD R8, R8, #1 CMP R8, #6 ; six characters in the table BLO %BT01 EXIT ; Compare a UCS-4 character against the WimpSymbol mapping bitmap, to see if it needs to be mapped ; Entry: R2 = alphabet ; R3 = icon's font handle ; R9 = UCS-4 character ; R11 = mapping bitmap (as set up in measure_symbols) ; Exit: EQ => needs mapping test_arrow ROUT [ RegisterWIMPSymbolFont Push "LR" CMP R9, #&80 Pull "PC", LO ; optimisation for ASCII: return NE Push "R0,R1" TEQ R2, #ISOAlphabet_UTF8 ADRNE R0, wimpsymbols ADREQ R0, wimpsymbols_UCS4 MOV R1, #0 ; index into symbol list 01 LDR R14, [R0, R1, LSL#2] CMP R9, R14 BEQ %FT02 ADD R1, R1, #1 CMP R1, #6 ; six characters in table BNE %BT01 CMP PC, #0 Pull "R0,R1,PC" ; return NE 02 ; we've found a character from the list - what does R11 say? TEQ R11, #0 ; not calculated yet? BLEQ measure_symbols ; work it out if so MOV R14, #1 TST R11, R14, LSL R1 ; set Z according to R1-th bit of R11 Pull "R0,R1,PC" | TEQ PC, #0 ; clear Z - no WIMPSymbol font fitted MOV PC, LR ] LTORG ] END