; 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.
;
;;----------------------------------------------------------------------------
;; Create/Delete icon on icon bar
;; userblk --> user's original block
;; handle = -1 ==> right side from left edge with priority 0
;;          -2 ==> left side from right edge with priority 0
;;          -3 ==> to left of existing icon in R0            Wimp 2.21 onwards
;;                 - or extreme left if R0 < 0
;;          -4 ==> to right of existing icon in R0           Wimp 2.21 onwards
;;                 - or extreme right if R0 < 0
;;          -5 ==> left side from left edge with R0 = priority    2.73 onwards
;;          -6 ==> left side from right edge with R0 = priority   2.73 onwards
;;          -7 ==> right side from left edge with R0 = priority   2.73 onwards
;;          -8 ==> right side from right edge with R0 = priority  2.73 onwards
;; R0 = handle of icon to open next to (if used)
;;      if icon not found, move to extreme left/right of iconbar
;;----------------------------------------------------------------------------

icbf_rightside  *       1 :SHL: 0       ; 1 => start from right, else left
icbf_r0handle   *       1 :SHL: 1       ; 1 => R0 = icon handle
icbf_r0priority *       1 :SHL: 2       ; 1 => R0 = priority level
icbf_fromedge   *       1 :SHL: 7       ; 1 => scan from edge, else middle
                                        ; MUST be highest-order bit
iconbartab
        DCB     icbf_rightside                                          ; right, from left , priority 0
        DCB     0                                                       ; left , from right, priority 0
        DCB     icbf_fromedge :OR: icbf_r0handle                        ; left , from left , r0 handle
        DCB     icbf_rightside :OR: icbf_fromedge :OR: icbf_r0handle    ; right, from right, r0 handle
        DCB     icbf_fromedge :OR: icbf_r0priority                      ; left , from left , r0 priority
        DCB     icbf_r0priority                                         ; left , from right, r0 priority
        DCB     icbf_rightside :OR: icbf_r0priority                     ; right, from left,  r0 priority
        DCB     icbf_rightside :OR: icbf_fromedge :OR: icbf_r0priority  ; right, from right, r0 priority
iconbartabsize  * .-iconbartab
        ALIGN

addtoiconbar

; work out whereabouts in the list to put the new icon

        CMN     handle, #iconbartabsize
        MyXError  WimpBadHandle, MI, L
        BVS     ExitWimp

        ADRL    R14,iconbartab-1
        LDRB    R14,[R14,-handle]       ; R14 = flag byte

        TST     R14,#icbf_rightside
        ADREQ   R7,iconbarleft
        ADRNE   R7,iconbarright

        TST     R14,#icbf_r0handle
        BNE     gofindit

        TST     R14,#icbf_r0priority
        MOVEQ   R0,#0                   ; default is priority 0

addwithpriority                         ; R0 = priority of icon to add
        ADD     R1,R7,#icd_list-icb_link
01
        LDR     R4,[R1,#icb_link]       ; R4 -> next icon block
        CMP     R4,#nullptr
        BEQ     %FT02
        LDR     R3,[R4,#icb_priority]
        Debug   icb,"Iconblk, priority, newpriority:",R4,R3,R0
        CMP     R0,R3
        CMPEQ   R14,#icbf_fromedge      ; icbf_fromedge is highest order bit
        MOVLT   R1,R4
        BLT     %BT01
02                                      ; now r1 -> block before one to insert
        B       addtoR1
        MakeErrorBlock WimpBadIconHandle

gofindit
        MOVS    R4,R0                   ; R4 = icon handle to open next to
        MOVMI   R0,#WimpPriority_Maximum
        BMI     addwithpriority

        MOV     R3,R7                   ; R3 -> default end to add to
        BL      findicon                ; R1 -> previous, R2 -> current, R7 -> left/right head pointer
        MyXError  WimpBadIconHandle,NE
        BVS     ExitWimp

        LDR     R0,[R2,#icb_priority]   ; inherit matched icon's priority
        TEQ     R7,R3                   ; if not same as default end,
        LDRNE   R1,[R1,#icb_link]       ; move in to next icon

        ; now drop through to addtoR1

; in    R0 = priority to give to the new icon
;       R1 -> block prior to where the new one is going
;       R7 -> iconbar left/right chain head

addtoR1
        Push    "R0"                    ; save priority level

; create iconbar window if necessary

        LDR     handle,iconbarhandle
        BL      checkhandle             ; V set ==> not created yet
        BVC     %FT01                   ; skip this if already present
;
        Push    "R2,R3,R7,userblk"      ; iconbar ptr, original R1 from user
;
        ADR     R0,wn_iconbar
        MOV     R2,#0                   ; no indirected icons allowed!
        MOV     R3,#0
        BL      createsystemp           ; R0,handle = window rel/abs handles
        STRVC   R0,iconbarhandle
        LDRVC   R14,[handle,#w_way1]
        LDRVC   R2,[handle,#w_way0]
        SUBVC   R14,R14,R2
        STRVC   R14,iconbarheight       ; used later
 [ HideIconBar
        MOVVC   R2, #-3
 |
        LDRVC   R2,iconbarhandle        ; open at same height
 ]
        BLVC    openiconbar
;
        Pull    "R2,R3,R7,userblk"
        BVS     %FT99
01

; create icon and associated block (R0 is still stacked!)

        Push    "R1,cx0,cy0,cx1,cy1,x0,y0,x1,y1"
;
        LDMIA   userblk,{R0,cx0,cy0,cx1,cy1,x0,y0,x1,y1}
        Push    "R0,cx0,cy0,cx1,cy1,x0,y0,x1,y1"
        MOV     userblk,sp              ; copy icon onto the stack
; 322nk store default width
        SUB     R14,cx1,cx0
        STR     R14,tempworkspace+16
;
; 320nk, adjust size of icon if text too big in current font
        TST     x0,#if_text             ; x0 is flags
        BEQ     %FT10
        Push    "R0-R2"
        ADD     R1,sp,#36               ; 12 (Push) +4 (icon block) +20 (icon data)
        TST     x0,#if_indirected
        BEQ     %FT05
; if indirected can be turned off with validation X
        Push    R3
        LDR     R3,[R1,#4]
        MOV     R2,#WimpValidation_NoAuto
        BL      findcommand
        Pull    R3
        BEQ     %FT9                    ; found X
        LDR     R1,[R1]
05
        MOV     R0,#1
        MOV     R2,#0                   ; don't stop!
        SWI     XWimp_TextOp            ; R0 now has width
        LDR     R14,dx
        ADD     R0,R0,R14, LSL #1       ; add on 2 dx for luck
        SUB     R1,cx1,cx0
        SUBS    R0,R0,R1
        Pull    "R0-R2",MI
        BMI     %FT10
        ADD     cx1,cx1, R0
        STR     cx1,[sp,#24]
09
        Pull    "R0-R2"
10
        BL      int_create_icon         ; on exit R0 = icon handle
        ADD     sp,sp,#4+i_size         ; correct stack
        Pull    "R1,cx0,cy0,cx1,cy1,x0,y0,x1,y1"
;
        Pull    "R4"                    ; R4 = priority to set
;
        Push    "R0"                    ; used later
        MOVVC   R3,#icb_size
        BLVC    claimblock
        BVS     %FT99                           ; couldn't create block

; link new block into chain, and initialise various fields
; in    [sp] = icon handle
;       R1 -> block after which R2 is to be linked
;       R2 -> new icon block
;       R4 = priority to set
;       R7 -> head of appropriate chain (left or right)

        STR     R4,[R2,#icb_priority]
;
        LDR     R14,[R1,#icb_link]              ; don't assume link is null
        STR     R14,[R2,#icb_link]
        STR     R2,[R1,#icb_link]
;
        LDR     R14,[sp,#0*4]                   ; R14 = icon handle
        STR     R14,[R2,#icb_iconhandle]
;
        LDR     R14,tempworkspace+16
        STR     R14,[R2,#icb_defwidth]

        LDR     R14,taskhandle                  ; R14 = task handle
        STR     R14,[R2,#icb_taskhandle]        ; NB no version bits internally
;
        BL      recalcposns
99
        STRVS   R0,[sp,#0*4]

        LDR     R14,taskhandle
        Debug   swp,"iconbar task handle is ",R14
        LDR     R14,[wsptr,R14]
        LDR     R0,[R14,#task_priority]
        ORR     R0,R0,#priority_iconbar
        STR     R0,[R14,#task_priority]
        Debug   swp,"Priority (ICONBAR ICON) ",R0

        Pull    "R0"
        B       ExitWimp

wn_iconbar      DCB     "iconbar",0     ; must be word-aligned
                ALIGN

;
; Entry:  R0 --> window identifier
;         R2,R3 --> indirected icon data start/end
; Exit:   R0,handle = handle of window (read from WindowManager:Templates)
;

createsystemp
        Push    "R1-R6,userblk,LR"
;
        LDMIA   R0,{R4-R6}
        Push    "R4-R6"                 ; Save window ident on stack
;
        ADR     R1,wimptempfname
        BL      int_open_template
        BVS     %FT99
;
        LDR     R2,[sp,#12+1*4]         ; 12 byte name, then R1-R6
        LDR     R3,[sp,#12+2*4]
        MOV     R4,#0                   ; no fancy fonts!
        MOV     R5,sp                   ; R5 --> identifier
        MOV     R6,#0                   ; 1st entry
        MOV     userblk,#-1             ; Check space reqd
        BL      int_load_template       ; Read template

        Debug   systmpl,"Template buffer size, data size, count",R1,R2,R6

        TEQ     R6,#0                   ; Any entries?
        MyXError  WimpNoTemplate,EQ     ; No then error
        MOVVC   R3,R1                   ; Size of scratch buffer reqd
        BLVC    claimblock              ; Claim from RMA
        MOVVS   userblk,#0              ; No memory claimed if error
        MOVVC   userblk,R2              ; Get-> claimed block
        LDRVC   R2,[sp,#12+1*4]         ; 12 byte name, then R1-R6
        LDRVC   R3,[sp,#12+2*4]
        MOVVC   R4,#0                   ; no fancy fonts!
        MOVVC   R6,#0                   ; search whole of index

        Debug   systmpl,"Loading template to",userblk

        BLVC    int_load_template
        MOVVC   R14, #0                 ; created window will be 'owned' by Wimp
        STRVC   R14, createwindowtaskhandle
        BLVC    int_create_window       ; R0,handle = window handles (if V clr)
        MOV     R14, #1                 ; subsequent windows are 'owned' by their creators
        STR     R14, createwindowtaskhandle

        MOVVC   R14,#1
        STRVC   R14,[handle,#w_areaCBptr]       ; use common sprite pool
98
        SavePSR R14
        Push    "R0,R14"                 ; Save flags
        TEQ     userblk,#0
        MOVNE   R2,userblk              ; userblk --> window block
        MOVNE   R0,#ModHandReason_Free

        Debug   systmpl,"Freeing block",userblk

        BLNE   XROS_Module
        BL      int_close_template
        Pull    "R0,R14"
        RestPSR R14,,f                  ; Restore V flag
99
        ADD     sp,sp,#12               ; lose copy of name
        Pull    "R1-R6,userblk,PC"
        MakeErrorBlock WimpNoTemplate

        [ NewErrorSystem
wimptempfname   DCB     "WindowManager:Templates",0     ; AMcC 18-Oct-94 was Template3D
        |
wimptempfname   DCB     "WindowManager:Templates",0
        ]
                ALIGN


; (Re)open iconbar in appropriate position for the current mode
; In    R2 = handle of window to open iconbar behind
; Out   handle -> window data of iconbar (ie. absolute handle)

            ASSERT  handle = R10        ; we want to return this
openiconbar Entry   "R1-R9,R11"

        LDR     R0,iconbarhandle
        CMP     R0,#nullptr
        EXIT    EQ
        MOV     handle,R0
        BL      checkhandle
        EXIT    VS

; try to keep things the same as before
; however, we must ensure that the extent is big enough for the OpenWindow

        ADR     R14,scrx0
        LDMIA   R14,{cx0,cy0,cx1,cy1}           ; always open iconbar at bottom
        LDR     R14,iconbarheight
        ADD     cy1,cy0,R14
      [ ThreeDPatch
        LDR     R14,ThreeDFlags
        TST     R14,#ThreeDFlags_NoIconBarBorder
        MOVNE   R14,#255                        ; no border special value
        MOVEQ   R14,#sc_black
        STRB    R14,[handle,#w_tfcol]           ; transfer border visual flag to window definition

        MOVNE   R14,#0                          ; no left/right border allowance
        MOVNE   R11,#0
        LDREQ   R14,dx
        LDREQ   R11,dy
      |
        LDR     R14,dx
        LDR     R11,dy
      ]
        ADD     cx0,cx0,R14
        SUB     cx1,cx1,R14
        ADD     cy0,cy0,R11                     ; cx0,cy0,cx1,cy1 = screen posn
        LDR     x0,[handle,#w_wex0]             ; try to keep extent the same
        SUB     x1,cx1,cx0
        ADD     x1,x0,x1                        ; x0,x1 = extent
        LDR     R14,[handle,#w_wex1]
        CMP     x1,R14                          ; we need extent >= screen width
        MOVLT   x1,R14                          ; so the OpenWindow works

; ensure that the other variables are consistent with this new size

        STR     x0,iconbarleft+icd_extent       ; window version is the same
        STR     x1,iconbarright+icd_extent
        STR     x1,[handle,#w_wex1]             ; NB: pixel aligned

        SUB     R14,cx1,cx0
        STR     R14,iconbarleft+icd_widthoffset     ; +width from left to right
        RSB     R14,R14,#0
        STR     R14,iconbarright+icd_widthoffset    ; -width from right to left
        LDR     R14,iconbarleft+icd_width
        ADD     R14,x0,R14                      ; relative to extent

        STR     R14,iconbarleft+icd_middle
        LDR     R14,iconbarright+icd_width          ; widths initialised before
        SUB     R14,x1,R14                      ; relative to extent
        STR     R14,iconbarright+icd_middle

        LDR     x0,[handle,#w_scx]                  ; keep same scroll offsets
        LDR     y0,[handle,#w_scy]

      [ debugicb
        Push    "cy0,cy1"
        LDR     cy0,[handle,#w_wex0]
        LDR     cy1,[handle,#w_wex1]
        Debug   icb,"openic: iconbar =",cx0,cx1,x0, cy0,cy1
        Pull    "cy0,cy1"
      ]

        LDR     R14,[sp, #1*4]          ; R2 on entry = bhandle
        Push    "R0,cx0,cy0,cx1,cy1,x0,y0,R14"
        MOV     userblk,sp
        BL      int_open_window
        ADD     sp,sp,#u_ow1

        EXIT

;
; Entry:  R2 = icon handle
;         it tries the filing system and utilities sections in turn
;

removefromiconbar
        BL      int_removefromiconbar
        B       ExitWimp


int_removefromiconbar
        Push    "R1-R7,LR"
;
        Debug   ic,"Remove from icon bar: R2 =",R2
;
        ORR     R0,R2,#msh_iconbar      ; R0 = icon handle (+marker bit)
        BL      byemessages             ; delete relevant messages
;
        LDR     handle,iconbarhandle
        BL      checkhandle
        BLVC    int_deleteicon          ; no error if not found
;
        MOV     R4,R2                   ; R4 = icon handle
        BL      findicon                ; exit: R2 --> block (if found)
;
        LDREQ   R14,[R2,#icb_link]      ; remove from chain
        STREQ   R14,[R1,#icb_link]
        MOVEQ   R0,#ModHandReason_Free
        BLEQ   XROS_Module
;
        BL      recalcposns             ; ignore errors from ROS_Module here
;
        LDR     R5,iconbarleft+icd_list
        LDR     R6,iconbarright+icd_list
        TST     R5,R6                   ; both negative?
        Pull    "R1-R7,PC",PL
;
        LDR     R0,iconbarhandle
        CMP     R0,#nullptr
        MOVNE   R14,#nullptr            ; kill off iconbar if empty
        STRNE   R14,iconbarhandle
        BLNE    int_delete_window
;
        Pull    "R1-R7,PC"

;
; Entry:  R4 = icon handle
; Exit:   found: Z set
;                R1-->previous link
;                R2-->icon block
;                R7-->iconbarleft/right
;     not found: Z unset
;

findicon
        Push    "LR"
;
        ADR     R7,iconbarleft
        BL      tryfindicon
        ADRNE   R7,iconbarright
        BLNE    tryfindicon
;
        Pull    "PC"

tryfindicon
        Push    "LR"
        ADD     R1,R7,#icd_list-icb_link
01
        LDR     R2,[R1,#icb_link]
        CMP     R2,#nullptr
        BEQ     %FT02
        LDR     R14,[R2,#icb_iconhandle]
        TEQ     R14,R4
        MOVNE   R1,R2
        BNE     %BT01
;
        Pull    "PC"                    ; found (Z set)
02
        TEQ     R2,#0
        Pull    "PC"                    ; not found (Z unset)


;
; Recompute positions of icons (called from CreateIcon and DeleteIcon)
; In    R7 -> icon data for appropriate side of icon bar
;       handle -> window defn of iconbar (ie. absolute handle)
;

recalcposns
        Push    "R1-R9,userblk,LR"
;
        ADR     R8,iconbarleft          ; R8 --> other section
        TEQ     R8,R7
        ADREQ   R8,iconbarright
;
        Push    handle
        LDR     handle,[handle,#w_icons]
;
        MOV     x0,#0
        LDR     R1,[R7,#icd_list]
01
        CMP     R1,#nullptr
        LDRNE   R2,[R1,#icb_iconhandle]
        ADDNE   R14,handle,R2,LSL #i_shift
        LDRNE   cx0,[R14,#i_bbx0]
        LDRNE   cx1,[R14,#i_bbx1]
        SUBNE   cx1,cx1,cx0
        ADDNE   x0,x0,#iconbargap       ; allow for gap between icons
        ADDNE   x0,x0,cx1               ; plus width of icon itself
        LDRNE   R1,[R1,#icb_link]
        BNE     %BT01
;
        STR     x0,[R7,#icd_width]
;
        Debug   ic,"This/other side, width =",R7,R8,x0
;
; decide if this will fit inside one screen-width
;
        LDR     R0,iconbarleft + icd_width
        LDR     R1,iconbarright+ icd_width
        ADD     R1,R0,R1                ; total width of icons
        LDR     cx1,iconbarleft + icd_widthoffset
        SUB     cx1,cx1,#iconbarsepgap  ; gap between left and right
;
; if it fits:  start at the outside and go in
;  otherwise:  start at the inside and go out
;
        LDR     R0,[R8,#icd_widthoffset]        ; +- screenwidth
        CMP     R1,cx1
        BGT     startinmiddle
;
        LDR     R9,[R8,#icd_extent]             ; other end
        ADD     R9,R9,R0                        ; must still be pixel-aligned
        STR     R9,[R7,#icd_extent]
        CMP     R0,#0                           ; was that plus or minus?
        SUBPL   R14,R9,x0
        ADDMI   R14,R9,x0
        STR     R14,[R7,#icd_middle]            ; work back to middle
        Debug   ic,"Unlimited: extent,middle =",R9,R14
        B       allocateicons

startinmiddle
        CMP     R0,#0
        LDR     R14,[R8,#icd_middle]
        ADDPL   R14,R14,#iconbarsepgap
        SUBMI   R14,R14,#iconbarsepgap
        STR     R14,[R7,#icd_middle]
        ADDPL   R9,R14,x0
        SUBMI   R9,R14,x0
        STR     R9,[R7,#icd_extent]
        Debug   ic,"Limited: extent,middle =",R9,R14

;
; R0 (bit 31) ==> direction to move in
; R7 --> data for this set of icons
; R8 --> data for the other set of icons
; R9 = start x-coord for icons
;

allocateicons
        LDR     R2,[R7,#icd_list]
01
        CMP     R2,#nullptr
        BEQ     doneicons
;
        LDR     R3,[R2,#icb_iconhandle]
        ADD     R14,handle,R3,LSL #i_shift
        LDMIA   R14,{R3,R4,R5,R6}
        SUB     R5,R5,R3                        ; width of icon
;
        CMP     R0,#0                           ; direction
        ADDMI   R3,R9,#iconbargap
        ADDMI   R5,R3,R5
        MOVMI   R9,R5
        SUBPL   R9,R9,#iconbargap
        SUBPL   R3,R9,R5
        MOVPL   R5,R9
        MOVPL   R9,R3
        STMIA   R14,{R3,R4,R5,R6}
;
        LDR     R2,[R2,#icb_link]
        B       %BT01

;
; reset window extent, and check whether we must scroll
;
doneicons
        Pull    handle
;
        LDR     R14,iconbarleft + icd_extent
        LDR     R0,dx_1                         ; must be pixel-aligned
        BIC     R14,R14,R0
        STR     R14,[handle,#w_wex0]            ; poke direct!
        LDR     R0,[handle,#w_scx]
        CMP     R0,R14
        MOVLT   R0,R14
;
        LDR     R14,iconbarright+ icd_extent
        LDR     R1,dx_1                         ; must be pixel-aligned
        BIC     R14,R14,R1
        STR     R14,[handle,#w_wex1]            ; poke direct!
        LDR     R1,iconbarright + icd_widthoffset
        ADD     R14,R14,R1
        CMP     R0,R14
        MOVGT   R0,R14
;
; Poke these directly to stop the Wimp attempting to do a block copy
;
        STR     R0,[handle,#w_scx]              ; poke direct! (pixel aligned)
      [ ChildWindows
        STR     R0,[handle,#w_old_scx]          ; also old position
      ]
;
      [ debugicb
        ADD     R14,handle,#w_wax0
        LDMIA   R14,{cx0,cy0,cx1,cy1,x0,y0}
        LDR     cy0,[handle,#w_wex0]
        LDR     cy1,[handle,#w_wex1]
        Debug   icb,"recalc: iconbar =",cx0,cx1,x0, cy0,cy1
      ]
;
        MOV     x0,#-bignum
        MOV     y0,#-bignum
        MOV     x1,#bignum
        MOV     y1,#bignum
        BL      int_force_redraw                ; mark invalid
;
        Pull    "R1-R9,userblk,PC"

        [ true

resizeiconbaricons
; make sure widths of iconbar icons are ok in new font
        Push    "R0-R5,R7,handle,userblk,lr"
        MOV     R0,#0
        STRB    R0,iconbar_needs_rs
        LDR     handle,iconbarhandle
        CMP     handle,#nullptr
        Pull    "R0-R5,R7,handle,userblk,PC",EQ
        Abs     handle,handle
        LDR     R5,[handle,#w_icons]
        LDR     R3,[handle,#w_nicons]
        TEQ     R3,#0
        Pull    "R0-R5,R7,handle,userblk,PC",EQ            ; return if no icons
        LDR     R4,taskhandle
        Push    "R4"
        MOV     R4,#0
resizeicons_loop
        BL      findicon
        BNE     resizeicons_next
; R2 -> icon block
        LDR     R14,[R5,#i_flags]
        TST     R14,#if_text
        BEQ     resizeicons_next
        TST     R14,#if_indirected
        ADD     R1,R5,#i_data
        BEQ     %FT05
        LDR     R1,[R1]
        LDR     R0,[R2,#icb_taskhandle]
        CMP     R0,#0
        BMI     %FT05
        LDR     R14,orig_applicationspacesize
        CMP     R14,R1
        BLHI    mapslotinout
; so that indirected data is ok. Now R1-> text
        Push    "R2,R3"
        MOV     R2,#WimpValidation_NoAuto
        LDR     R3,[R5,#i_data+4]                 ; validation string
        BL      findcommand
        Pull    "R2,R3"
        BEQ     resizeicons_next
05
        MOV     R0,#1
        Push    "R2"
        MOV     R2,#0
        SWI     XWimp_TextOp
        LDR     R14,dx
        ADD     R0,R0,R14, LSL #1       ; add on 2 dx for luck

        Pull    "R2"
        LDR     R1,[R2,#icb_defwidth]
        CMP     R0,R1
        MOVHI   R1,R0
        LDR     R0,[R5,#i_bbx0]
        ADD     R1,R0,R1
        STR     R1,[R5,#i_bbx1]                 ; update width if needed

resizeicons_next
        SUBS    R3,R3,#1
        ADDNE   R5,R5,#i_size
        ADDNE   R4,R4,#1
        BNE     resizeicons_loop
        ADR     R7,iconbarleft
        BL      recalcposns
        ADR     R7,iconbarright
        BL      recalcposns
        ADR     R7,iconbarleft
        BL      recalcposns

        Pull    "R0"
        CMP     R0,#0
        BLPL    mapslotinout

        Pull    "R0-R5,R7,handle,userblk,PC"

mapslotinout
        Push    "R0-R2,R14"
        LDR     R1,taskhandle
        TEQ     R0,R1
        Pull    "R0-R2,PC",EQ
        LDR     R0,[R12,R1]                     ; task block
        TST     R0,#&80000000
        BNE     %FT01
        LDR     R0,[R0,#task_slotptr]
        CMP     R0,#nullptr
        BLNE    mapout
01
        Pull    "R0"
        LDR     R14,=&ffff
        AND     R0,R0,R14                    ; make sure internal t/h
        STR     R0,taskhandle
        LDR     R0,[R12,R0]
        TST     R0,#&80000000
        Pull    "R1-R2,PC",NE
        LDR     R0,[R0,#task_slotptr]
        CMP     R0,#nullptr
        BLNE    mapin
        Pull    "R1-R2,PC"
        ]

        END