                opt     l+,o+,ow-
*
*   gadget.s version 7.6 - © Copyright 1990 Jaba Development
*
*   Author    : Jan van den Baard
*   Assembler : Devpac version 2.14
*
        incdir  'sys:devpac_inc/'
        include 'mymacros.i'
        include 'exec/memory.i'
        include 'exec/exec_lib.i'
        include 'intuition/intuition.i'
        include 'intuition/intuition_lib.i'
        include 'graphics/graphics_lib.i'

        xref    _IntuitionBase
        xref    _GfxBase

        xdef    TestBits
        xdef    SelectGadget
        xdef    DeSelectGadget
        xdef    MutualExclude
        xdef    MutualInclude
        xdef    EraseGadget
        xdef    GadgetOn
        xdef    GadgetOff
        xdef    SelectTest
        xdef    ShadowGadget
        xdef    OnGList
        xdef    OffGList
        xdef    SelectGList
        xdef    DeSelectGList
        xdef    ShadowGList
        xdef    EraseGList

TestBits:       and.l   d1,d0
                cmp.l   d0,d1
                beq.s   BitsSet
                cldat   d0
                rts
BitsSet:        moveq   #1,d0
                rts


SelectGadget:   movem.l d2-d4/a2-a3/a6,-(sp)
                move.l  a0,d2                   ; window in d2
                move.l  a1,a3                   ; gadget in a3
                move.l  a2,d3                   ; requester in d3
                move.w  gg_Activation(a3),d0
                andi.w  #TOGGLESELECT,d0        ; TOGGLESELECT ?
                bne.s   IsTog                   ; yes, try to select it
EndSG:          movem.l (sp)+,d2-d4/a2-a3/a6
                rts
IsTog:          move.w  gg_Flags(a3),d0
                andi.w  #SELECTED,d0            ; SELECTED ?
                bne.s   EndSG                   ; yes, dont do anything
                bsr.s   SwitchSel               ; select it
                bra.s   EndSG

DeSelectGadget: movem.l d2-d4/a2-a3/a6,-(sp)
                move.l  a0,d2                   ; window in d2
                move.l  a1,a3                   ; gadget in a3
                move.l  a2,d3                   ; requester in d3
                move.w  gg_Activation(a3),d0
                andi.w  #TOGGLESELECT,d0        ; TOGGLESELECT ?
                bne.s   IsTogg                  ; yes, try to deselect it
EndDSG:         movem.l (sp)+,d2-d4/a2-a3/a6
                rts
IsTogg:         move.w  gg_Flags(a3),d0
                andi.w  #SELECTED,d0            ; SELECTED ?
                beq.s   EndDSG                  ; no, dont do anything
                bsr.s   SwitchSel               ; deselect it
                bra.s   EndDSG

SwitchSel:      move.l  a3,a0
                move.l  d2,a1
                move.l  d3,a2
                moveq   #1,d0
                move.l  _IntuitionBase,a6
                libcall RefreshGList            ; refresh the gadget
                move.l  d2,a0
                move.l  a3,a1
                moveq   #1,d0
                libcall RemoveGList             ; remove the gadget
                move.l  d0,d4
                eori.w  #SELECTED,gg_Flags(a3)  ; toggle selected flag
                move.l  d2,a0
                move.l  a3,a1
                move.l  d4,d0
                moveq   #1,d1
                move.l  d3,a2
                libcall AddGList                ; add the gadget
                move.l  a3,a0
                move.l  d2,a1
                move.l  d3,a2
                moveq   #1,d0
                libcall RefreshGList            ; refresh the gadget
                rts

MutualExclude:  movem.l d2-d6/a2-a3/a6,-(sp)
                move.l  a0,d2                   ; window in d2
                move.l  a1,a0                   ; gadget that excludes in a0
                move.l  a3,d3                   ; requester in d3
                move.l  a2,a3                   ; first gadget in a3
                move.l  gg_MutualExclude(a0),d5
                tst.l   d5                      ; mutual exclude bits set ?
                bne.s   MustExcl                ; yes, try to exclude them
EndME:          movem.l (sp)+,d2-d6/a2-a3/a6
                rts
MustExcl:       cldat   d6
ExclLoop:       btst    d6,d5                   ; bit set ?
                beq.s   NotExcl                 ; no, skip this one
                bchg    d6,d5                   ; clear bit
                move.l  d3,a2                   ; requester in a2
                move.l  a3,a1                   ; gadget in a1
                move.l  d2,a0                   ; window in a0
                bsr     DeSelectGadget          ; deselect the gadget
NotExcl:        cmpi.l  #31,d6                  ; had 32 bits ?
                beq.s   EndME                   ; yes, done
                inc.l   d6                      ; increase counter
                tst.l   d5                      ; bits left ?
                beq.s   EndME                   ; no, done
                move.l  gg_NextGadget(a3),a3
                cmpa.l  #0,a3                   ; gadgets left ?
                beq.s   EndME                   ; no, done
                bra.s   ExclLoop

MutualInclude:  movem.l d2-d6/a2-a3/a6,-(sp)
                move.l  a0,d2                   ; window in d2
                move.l  a1,a0                   ; gadget that includes in a0
                move.l  a3,d3                   ; requester in d3
                move.l  a2,a3                   ; firrst gadget in a3
                move.l  gg_MutualExclude(a0),d5
                tst.l   d5                      ; mutual include bits set ?
                bne.s   MustIncl                ; yes, try to include them
EndMI:          movem.l (sp)+,d2-d6/a2-a3/a6
                rts
MustIncl:       cldat   d6
InclLoop:       btst    d6,d5                   ; bit set ?
                beq.s   NotIncl                 ; no, skip this one
                bchg    d6,d5                   ; clear bit
                move.l  d3,a2                   ; requester in a2
                move.l  a3,a1                   ; gadget in a1
                move.l  d2,a0                   ; window in a0
                bsr     SelectGadget            ; select the gadget
NotIncl:        cmpi.l  #31,d6                  ; had 32 bits ?
                beq.s   EndMI                   ; yes, done
                inc.l   d6                      ; increase counter
                tst.l   d5                      ; bits left ?
                beq.s   EndMI                   ; no, done
                move.l  gg_NextGadget(a3),a3
                cmpa.l  #0,a3                   ; gadgets left ?
                beq.s   EndMI                   ; no, done
                bra.s   InclLoop

EraseGadget:    movem.l d2-d4/a2-a3/a6,-(sp)
                move.l  a0,d2                   ; window in d2
                move.l  a1,a3                   ; gadget in a3
                move.l  a2,d3                   ; requester in d3
                tst.l   d3                      ; is ther a requester ?
                beq.s   NotReq                  ; no.. use window rastport
                move.l  d3,a0
                move.l  rq_ReqLayer(a0),a0
                move.l  lr_rp(a0),a0            ; layer rastport to a0
                bra.s   GotRP
NotReq:         move.l  d2,a0
                move.l  wd_RPort(a0),a0         ; get window rastport
GotRP:          move.l  a0,d4                   ; rastport to d4
                cldat   d0
                move.b  rp_DrawMode(a0),d0      ; old drawmode to d0
                move.l  d0,-(sp)                ; save old DrawModes
                move.l  d4,a1
                tst.l   d3                      ; is there a requester ?
                beq.s   BackGround              ; no
                move.l  d3,a0
                moveq   #0,d0
                move.b  rq_BackFill(a0),d0      ; requester backfill color
                bra.s   SetPen
BackGround:     cldat   d0                      ; use color 0
SetPen:         move.l  _GfxBase,a6
                libcall SetAPen                 ; set frontpen
                move.l  d4,a1
                moveq   #RP_JAM1,d0
                libcall SetDrMd                 ; set drawmodes
                move.l  a3,a0
                move.l  d2,a1
                move.l  d3,a2
                moveq   #1,d0
                move.l  _IntuitionBase,a6
                libcall RefreshGList            ; refresh the gadget
                move.l  d4,a1
                movem.l d2/d3,-(sp)
                cldat   d0
                cldat   d1
                cldat   d2
                cldat   d3
                move.w  gg_LeftEdge(a3),d0
                dec.w   d0
                move.w  gg_TopEdge(a3),d1
                dec.w   d1
                move.w  d0,d2
                move.w  d1,d3
                inc.w   d2
                inc.w   d3
                add.w   gg_Width(a3),d2
                add.w   gg_Height(a3),d3
                move.l  _GfxBase,a6
                libcall RectFill                ; clear gadget area
                movem.l (sp)+,d2/d3
                move.l  gg_GadgetText(a3),d0
                tst.l   d0
                beq     NoTexts                 ; branch if no texts
                move.l  d0,-(sp)
                move.l  #it_SIZEOF,d0
                move.l  #MEMF_PUBLIC+MEMF_CLEAR,d1
                move.l  _SysBase,a6
                libcall AllocMem                ; allocate text buffer
                move.l  (sp)+,a0
                move.l  d0,a2
                beq.s   NoTexts
TextLoop:       move.l  it_IText(a0),it_IText(a2)
                move.l  it_ITextFont(a0),it_ITextFont(a2)
                move.w  it_TopEdge(a0),it_TopEdge(a2)
                move.w  it_LeftEdge(a0),it_LeftEdge(a2)
                move.b  #RP_JAM2,it_DrawMode(a2)
                tst.l   d3
                beq.s   Null
                move.l  d3,a1
                move.b  rq_BackFill(a1),it_FrontPen(a2)
                move.b  rq_BackFill(a1),it_BackPen(a2)
Null:           move.l  it_NextText(a0),-(sp)
                move.l  d4,a0
                move.l  a2,a1
                cldat   d0
                cldat   d1
                move.w  gg_LeftEdge(a3),d0
                move.w  gg_TopEdge(a3),d1
                move.l  _IntuitionBase,a6
                libcall PrintIText              ; erase the texts
                move.l  (sp)+,d0
                tst.l   d0
                beq.s   NoMoreTexts             ; branch if all text erased
                move.l  d0,a0
                bra.s   TextLoop
NoMoreTexts:    move.l  a2,a1
                move.l  #it_SIZEOF,d0
                move.l  _SysBase,a6
                libcall FreeMem                 ; free the text buffer
NoTexts:        move.l  d4,a1
                move.l  (sp)+,d0
                move.l  _GfxBase,a6
                libcall SetDrMd                 ; reset old DrawModes
                movem.l (sp)+,d2-d4/a2-a3/a6
                rts

GadgetOn:       movem.l d2-d4/a2-a3/a6,-(sp)
                move.l  a0,d2                   ; window in d2
                move.l  a1,a3                   ; gadget in a3
                move.l  a2,d3                   ; requester in d3
                move.w  gg_Flags(a3),d0
                andi.w  #GADGDISABLED,d0        ; GADGDISABLED  ?
                beq.s   EndGON                  ; no, dont do anything
                bsr.s   SwitchDis               ; switch gadget on
EndGON:         movem.l (sp)+,d2-d4/a2-a3/a6
                rts

GadgetOff:      movem.l d2-d4/a2-a3/a6,-(sp)
                move.l  a0,d2                   ; window in d2
                move.l  a1,a3                   ; gadget in a3
                move.l  a2,d3                   ; requester in d3
                move.w  gg_Flags(a3),d0
                andi.w  #GADGDISABLED,d0        ; GADGDISABLED ?
                bne.s   EndGOF                  ; yes, dont do anything
                bsr.s   SwitchDis               ; switch gadget off
EndGOF:         movem.l (sp)+,d2-d4/a2-a3/a6
                rts

SwitchDis:      move.l  d3,a2
                move.l  a3,a1
                move.l  d2,a0
                bsr     EraseGadget             ; erase the gadget
                move.l  d2,a0
                move.l  a3,a1
                moveq   #1,d0
                move.l  _IntuitionBase,a6
                libcall RemoveGList             ; remove the gadget
                eori.w  #GADGDISABLED,gg_Flags(a3) ; flip the GADGDISABLED flag
                move.l  d2,a0
                move.l  a3,a1
                moveq   #1,d1
                move.l  d3,a2
                libcall AddGList                ; add the gadget
                move.l  a3,a0
                move.l  d2,a1
                move.l  d3,a2
                moveq   #1,d0
                libcall RefreshGList            ; refresh the gadget
                rts

SelectTest:     move.w  gg_Flags(a0),d0
                andi.w  #SELECTED,d0            ; SELECTED set ?
                bne.s   IsSelected              ; yes
                cldat   d0
                rts
IsSelected:     moveq   #1,d0
                rts

ShadowGadget:   movem.l d2-d7/a2-a3/a6,-(sp)
                move.l  a0,d2                   ; window in d2
                move.l  a1,a3                   ; gadget in a3
                move.l  a2,d3                   ; requester in d3
                move.l  d0,d4                   ; color in d4
                tst.l   d3                      ; is there a requester ?
                beq.s   NoReq                   ; no
                move.l  d3,a0
                move.l  rq_ReqLayer(a0),a0
                move.l  lr_rp(a0),a0            ; get requester rastport
                bra.s   RP
NoReq:          move.l  d2,a0
                move.l  wd_RPort(a0),a0         ; get window rastport
RP:             move.l  a0,a2                   ; rastport to a2
                cldat   d0
                move.b  rp_DrawMode(a0),d0
                move.l  d0,-(sp)                ; save old DrawModes
                moveq   #RP_JAM1,d0
                move.l  a2,a1
                move.l  _GfxBase,a6
                libcall SetDrMd                 ; set drawmodes
                move.l  d4,d0
                move.l  a2,a1
                libcall SetAPen                 ; set frontpen
                cldat   d4
                cldat   d5
                cldat   d6
                cldat   d7
                move.w  gg_LeftEdge(a3),d4
                move.w  gg_TopEdge(a3),d5
                move.w  gg_Width(a3),d6
                move.w  gg_Height(a3),d7
                add.w   d5,d7
                add.w   d4,d6
                move.l  a2,a1
                move.l  d6,d0
                inc.l   d0
                move.l  d5,d1
                addq.l  #2,d1
                libcall Move                    ; move cursor
                move.l  a2,a1
                move.l  d6,d0
                inc.l   d0
                move.l  d7,d1
                inc.l   d1
                libcall Draw                    ; draw a line
                move.l  a2,a1
                move.l  d6,d0
                addq.l  #2,d0
                move.l  d5,d1
                addq.l  #2,d1
                libcall Move                    ; move cursor
                move.l  a2,a1
                move.l  d6,d0
                addq.l  #2,d0
                move.l  d7,d1
                inc.l   d1
                libcall Draw                    ; draw a line
                move.l  a2,a1
                move.l  d4,d0
                addq.l  #4,d0
                move.l  d7,d1
                inc.l   d1
                libcall Move                    ; move cursor
                move.l  a2,a1
                move.l  d6,d0
                inc.l   d0
                move.l  d7,d1
                inc.l   d1
                libcall Draw                    ; draw a line
                move.l  a2,a1
                move.l  (sp)+,d0
                libcall SetDrMd                 ; reset old DrawModes
                movem.l (sp)+,d2-d7/a2-a3/a6
                rts

OnGList:        movem.l d2-d5/a2,-(sp)
                move.l  a0,d2                   ; window in d2
                move.l  d0,d4                   ; numgadgets in d4
                move.l  a1,d0                   ; gadget in d0
                move.l  a2,d3                   ; requester in d3
                cldat   d5
OnLoop:         move.l  d0,a2                   ; gadget to a2
                tst.l   d0                      ; anymore gadgets ?
                beq.s   NoMoreOn                ; no, done
                move.l  a2,-(sp)
                move.l  d2,a0                   ; window in a0
                move.l  a2,a1                   ; gadget in a1
                move.l  d3,a2                   ; requester in a2
                bsr     GadgetOn                ; switch gadget on
                move.l  (sp)+,a2
                inc.l   d5                      ; increase counter
                cmp.l   d5,d4                   ; all done ?
                beq.s   NoMoreOn                ; yes
                move.l  gg_NextGadget(a2),d0
                bra.s   OnLoop
NoMoreOn:       movem.l (sp)+,d2-d5/a2
                rts

OffGList:       movem.l d2-d5/a2,-(sp)
                move.l  a0,d2                   ; window in d2
                move.l  d0,d4                   ; numgadgets in d4
                move.l  a1,d0                   ; gadget in d0
                move.l  a2,d3                   ; requester in d3
                cldat   d5
OffLoop:        move.l  d0,a2
                tst.l   d0                      ; any more gadgets ?
                beq.s   NoMoreOff               ; no, done
                move.l  a2,-(sp)
                move.l  d2,a0
                move.l  a2,a1
                move.l  d3,a2
                bsr     GadgetOff               ; switch gadget off
                move.l  (sp)+,a2
                inc.l   d5                      ; increase counter
                cmp.l   d5,d4                   ; all done ?
                beq.s   NoMoreOff               ; yes
                move.l  gg_NextGadget(a2),d0
                bra.s   OffLoop
NoMoreOff:      movem.l (sp)+,d2-d5/a2
                rts

SelectGList:    movem.l d2-d5/a2,-(sp)
                move.l  a0,d2                   ; window in d2
                move.l  d0,d4                   ; numgadgets in d4
                move.l  a1,d0                   ; gadget in d0
                move.l  a2,d3                   ; requester in d3
                cldat   d5
SelLoop:        move.l  d0,a2
                tst.l   d0
                beq.s   NoMoreSel
                move.l  a2,-(sp)
                move.l  d2,a0
                move.l  a2,a1
                move.l  d3,a2
                bsr     SelectGadget
                move.l  (sp)+,a2
                inc.l   d5
                cmp.l   d5,d4
                beq.s   NoMoreSel
                move.l  gg_NextGadget(a2),d0
                bra.s   SelLoop
NoMoreSel:      movem.l (sp)+,d2-d5/a2
                rts

DeSelectGList:  movem.l d2-d5/a2,-(sp)
                move.l  a0,d2                   ; window in d2
                move.l  d0,d4                   ; numgadgets in d4
                move.l  a1,d0                   ; gadget in d0
                move.l  a2,d3                   ; requester in d3
                cldat   d5
DSelLoop:       move.l  d0,a2
                tst.l   d0
                beq.s   NoMoreDSel
                move.l  a2,-(sp)
                move.l  d2,a0
                move.l  a2,a1
                move.l  d3,a2
                bsr     DeSelectGadget
                move.l  (sp)+,a2
                inc.l   d5
                cmp.l   d5,d4
                beq.s   NoMoreDSel
                move.l  gg_NextGadget(a2),d0
                bra.s   DSelLoop
NoMoreDSel:     movem.l (sp)+,d2-d5/a2
                rts

ShadowGList:    movem.l d2-d6/a2,-(sp)
                move.l  a0,d2                   ; window in d2
                move.l  d0,d6                   ; color in d6
                move.l  d1,d4                   ; numgadgets in d4
                move.l  a1,d0                   ; gadget in d0
                move.l  a2,d3                   ; requester in d3
                cldat   d5
ShadLoop:       move.l  d0,a2
                tst.l   d0
                beq.s   NoMoreShad
                move.l  a2,-(sp)
                move.l  d2,a0
                move.l  a2,a1
                move.l  d3,a2
                move.l  d6,d0
                bsr     ShadowGadget
                move.l  (sp)+,a2
                inc.l   d5
                cmp.l   d5,d4
                beq.s   NoMoreShad
                move.l  gg_NextGadget(a2),d0
                bra.s   ShadLoop
NoMoreShad:     movem.l (sp)+,d2-d6/a2
                rts

EraseGList:     movem.l d2-d5/a2,-(sp)
                move.l  a0,d2                   ; window in d2
                move.l  d0,d4                   ; numgadgets in d4
                move.l  a1,d0                   ; gadget in d0
                move.l  a2,d3                   ; requester in d3
                cldat   d5
ErasLoop:       move.l  d0,a2
                tst.l   d0
                beq.s   NoMoreEras
                move.l  a2,-(sp)
                move.l  d2,a0
                move.l  a2,a1
                move.l  d3,a2
                bsr     EraseGadget
                move.l  (sp)+,a2
                inc.l   d5
                cmp.l   d5,d4
                beq.s   NoMoreEras
                move.l  gg_NextGadget(a2),d0
                bra.s   ErasLoop
NoMoreEras:     movem.l (sp)+,d2-d5/a2
                rts

