; tls_stuff.i      Version 1.00   10th February, 2002

*>>************************************************************************
*
*   Subroutines to open windows with scrollers
*   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
*   The xxp_slis and xxp_scro structures must already be defined before
*   these subroutines can be assembled.
*
*
*   Call TLSlis for every screen which will have windows with scrollers
*       Call TLScro before each window opened
*           Call TLSOpenWindow to open each window
*
*               Call TLSupdate when IDCMP_ come from the window
*               Call TLScroll to set the window scrollers
*
*           Call TLSCloseWindow to match each successful TLSOpenWindow
*       Call TLScrk to match each successful TLScro
*   Call TLSlik to match each successful TLSlis
*
***************************************************************************


 IFND TLS_Stuff


TLS_Stuff: SET 1


*>> Open a window with scrollers

; TLScro must have been successfully called
; If TLSOpenWindow fails, call TLScrk to match TLScro
; If TLSOpenWindow fails, match it with a call to TLSCloseWindow

; d0 = min width   (max/4 if null)  minimum 40   }
; d1 = min height  (max/4 if null)  minimum 20   }
; d2 = init width  (max/2 if null)               }    d0-d7 are corrected
; d3 = init height (max/2 if null)               }    if invalid
; d4 = max width   (screen width if null)        }
; d5 = max height  (screen height if null)       }
; d6 = xpos        (horz centre of screen if -1) }
; d7 = ypos        (vert centre of screen if -1) }

; d7 has bit 31 set if a0 is a custom (i.e. non-public) screen

; a0 = screen
; a1 = xxp_scro for which TLScro called, or a1=0 if no scrollers
; a2 = title - pointer to null delimited string
; a3 = 0(a3) = flags, 4(a3) = IDCMP
; a6 = intuition.library base


TLSOpenWindow:
 movem.l d0-d7/a0-a6,-(a7) ;save all except result in d0

 tst.w d4                  ;set d4 to screen width if null
 ble.s .mxxf
 cmp.w #40,d4              ;d4 must be >= 40
 bcc.s .mxxl
 moveq #40,d4
.mxxl:
 cmp.w sc_Width(a0),d4     ;d4 must be <= screen width
 bls.s .maxx
.mxxf:
 move.w sc_Width(a0),d4
.maxx:
 tst.w d5                  ;set d5 to screen height if null
 ble.s .mxyf
 cmp.w #20,d5              ;d5 must be >= 20
 bcc.s .mxyl
 moveq #20,d5
.mxyl:
 cmp.w sc_Height(a0),d5    ;d5 must be <= screen height
 bls.s .maxy
.mxyf:
 move.w sc_Height(a0),d5
.maxy

 tst.w d0                  ;d0 = d4/4 if null
 bgt.s .mnxf
 move.w d4,d0
 addq.w #3,d0
 lsr.w #2,d0
.mnxf:
 cmp.w d0,d4               ;d0 must be <= d4
 bcc.s .minl
 move.w d4,d0
.minl:
 cmp.w #40,d0              ;d0 must be >= 40
 bcc.s .minx
 moveq #40,d0
.minx:
 tst.w d1                  ;d1 = d5/4 if null
 bgt.s .mnyf
 move.w d5,d1
 addq.w #3,d1
 lsr.w #2,d1
.mnyf:
 cmp.w d1,d5               ;d1 must be <= d5
 bcc.s .mnyl
 move.w d5,d1
.mnyl:
 cmp.w #20,d1              ;d1 must be >= 20
 bcc.s .miny
 moveq #20,d1
.miny:

 tst.w d2                  ;d2 = d4/2 if null
 bgt.s .mdxf
 move.w d4,d2
 addq.w #1,d2
 lsr.w #1,d2
.mdxf:
 cmp.w d0,d2               ;d2 must be >= d0
 bcc.s .mdxl
 move.w d0,d2
.mdxl:
 cmp.w d2,d4               ;d2 must be <= d4
 bcc.s .midx
 move.w d4,d2
.midx:
 tst.w d3                  ;d3 = d5/2 if null
 bgt.s .mdyf
 move.w d5,d3
 addq.w #1,d3
 lsr.w #1,d3
.mdyf:
 cmp.w d1,d3               ;d3 must be >= d1
 bcc.s .mdyl
 move.w d1,d3
.mdyl:
 cmp.w d3,d5               ;d3 must be <= d5
 bcc.s .midy
 move.w d5,d3
.midy:

 move.l d0,-(a7)
 move.w sc_Width(a0),d0    ;d6 must be <= screen width - d2
 sub.w d2,d0
 tst.w d6
 bpl.s .xpfx
 move.w d0,d6              ;horz centre of screen if d6 < 0
 lsr.w #1,d6
.xpfx:
 cmp.w d6,d0
 bcc.s .xpos
 move.w d0,d6
.xpos:
 move.w sc_Height(a0),d0   ;d7 must be <= screen height - d3
 sub.w d3,d0
 tst.w d7
 bpl.s .ypfx
 move.w d0,d7              ;vert centre of screen if d7 < 0
 lsr.w #1,d7
.ypfx:
 cmp.w d7,d0
 bcc.s .ypos
 move.w d0,d7
.ypos:
 move.l (a7)+,d0

 sub.w #132,a7             ;room for 16 tags (actually 13)
 move.l a7,a5

 move.l #WA_Flags,(a5)+    ;flags
 move.l (a3),(a5)+
 move.l #WA_IDCMP,(a5)+    ;idcmp
 move.l 4(a3),(a5)+
 move.l #WA_Title,(a5)+    ;title
 move.l a2,(a5)+

 move.l #WA_PubScreen,(a5)+ ;send screen (bit31 of d7 set if private)
 tst.l d7
 bpl.s .pubs
 move.l #WA_CustomScreen,-4(a5)
.pubs:
 move.l a0,(a5)+

 move.l #WA_MinWidth,(a5)+ ;tags for window posn, dims
 clr.w (a5)+
 move.w d0,(a5)+
 move.l #WA_MinHeight,(a5)+
 clr.w (a5)+
 move.w d1,(a5)+
 move.l #WA_Width,(a5)+
 clr.w (a5)+
 move.w d2,(a5)+
 move.l #WA_Height,(a5)+
 clr.w (a5)+
 move.w d3,(a5)+
 move.l #WA_MaxWidth,(a5)+
 clr.w (a5)+
 move.w d4,(a5)+
 move.l #WA_MaxHeight,(a5)+
 clr.w (a5)+
 move.w d5,(a5)+
 move.l #WA_Left,(a5)+
 clr.w (a5)+
 move.w d6,(a5)+
 move.l #WA_Top,(a5)+
 clr.w (a5)+
 move.w d7,(a5)+

 move.l a1,d0              ;no scrollers if a1 = 0
 beq.s .call
 move.l #WA_Gadgets,(a5)+  ;scrollers = xxp_gcnt
 move.l xxp_gcnt(a1),(a5)+

.call:
 clr.l (a5)
 sub.l a0,a0
 move.l a7,a1
 jsr _LVOOpenWindowTagList(a6)
 add.w #132,a7

 move.l d0,(a7)            ;EQ, d0 = 0 if bad   else, d0 = window
 movem.l (a7)+,d0-d7/a0-a6
 rts


*>> process a message that might be from scrollers

; a0 = this window's xxp_scro
; a2 = message    returns D0 = 0 if not scrollers / no movement
; a5 = window
; a6 = intuition.library base

; returns D0 =  0 if not scrollers / no movement
; returns D0 = +1 and xxp_hztp altered
; returns D0 = -1 and xxp_vttp altered

TLSupdate:
 movem.l d0-d7/a0-a6,-(a7) ;save all except results

 clr.l (a7)                ;result = 0 pro-tem

 cmp.l #IDCMP_IDCMPUPDATE,im_Class(a2)  ;no if no an UPDATE
 bne .null
 cmp.l im_IDCMPWindow(a2),a5            ;no if not from this window
 bne .null

 move.l xxp_scre(a0),a1    ;a1 = xxp_slis for this window's screen

 moveq #-1,d3              ;set d3 = -1 if lmb down, else 0
 move.b im_Qualifier(a2),d0
 btst #1,d0
 bne.s .lmbo
 moveq #0,d3
 clr.l xxp_asec(a1)        ;if lmb up, kill asec, psec (no key repeat)
 clr.l xxp_amic(a1)
 clr.w xxp_srpt(a1)
 bra.s .rpdn

.lmbo:
 move.l im_Seconds(a2),d4  ;d4,d5 = seconds, micros
 move.l im_Micros(a2),d5

 move.l xxp_asec(a1),d0    ;if asec,amic = 0, go set asec,amic
 or.l xxp_amic(a1),d0
 beq.s .rpof

 sub.l xxp_asec(a1),d4     ;set d5 = microseconds since asec,amic
 bmi.s .rpof
 sub.l #1000000,d5
.calc:
 add.l #1000000,d5
 subq.b #1,d4
 bpl .calc
 sub.l xxp_amic(a1),d5
 bmi.s .rpof               ;go if -ve time elapsed (can't happen?)

 cmp.l #3000000,d4         ;repeat off if > 3 secs since last event
 bcc.s .rpof

 tst.w xxp_srpt(a1)        ;go if already repeating
 bne.s .repy

 cmp.l xxp_pmic(a1),d5     ;annul if < wait for repeat
 bcs .null
 subq.w #1,xxp_srpt(a1)    ;else, set repeat on
 bra.s .seta               ;& go process

.repy:
 cmp.l xxp_dmic(a1),d5     ;annul if repeating, < repeat speed
 bcs .null
 bra.s .seta               ;else, set repeat on

.rpof:
 clr.w xxp_srpt(a1)        ;here if repeat off

.seta:
 move.l im_Seconds(a2),xxp_asec(a1)  ;here to set time of this event
 move.l im_Micros(a2),xxp_amic(a1)

.rpdn:
 move.w im_MouseX(a2),d0
 bmi .null
 move.w im_MouseY(a2),d1
 bmi .null
 sub.w wd_Width(a5),d0     ;d0,d1 = -1 * dist from window bot right
 bpl .null
 sub.w wd_Height(a5),d1
 bpl .null
 moveq #0,d6
 move.b wd_BorderRight(a5),d6  ;d0,d1 = posn in rhs,bot border if +ve
 add.w d6,d0
 move.b wd_BorderBottom(a5),d6
 add.w d6,d1
 bmi.s .rbrd               ;go if not in bottom border
 tst.w d0
 bpl .null                 ;null if in both borders (can't happen?)

 move.l xxp_rtob(a1),a3    ;we are in bottom border...
 add.w ig_Width(a3),d0
 bpl.s .rtob
 add.w ig_Width(a3),d0
 bpl.s .lfob
 bra .horz

.rbrd:
 tst.w d0                  ;null if in both borders (can't happen?)
 bmi .null

 move.l xxp_upob(a1),a3    ;we are in right border...
 add.w ig_Height(a3),d1
 bpl.s .dnob
 add.w ig_Height(a3),d1
 bpl.s .upob
 bra .vert

.lfob:                     ;we are in left object...
 tst.w d3
 beq .null                 ;(null if lmb up)
 move.l xxp_hztp(a0),d0
 beq .null
 sub.l xxp_hstp(a0),d0
 bcc.s .bhfx
 moveq #0,d0
 bra.s .bhfx

.rtob:                     ;we are in right object...
 tst.w d3
 beq .null
 move.l xxp_hztt(a0),d1
 sub.l xxp_hzvs(a0),d1
 move.l xxp_hztp(a0),d0
 cmp.l d0,d1
 beq .null
 add.l xxp_hstp(a0),d0
 cmp.l d1,d0
 bls.s .bhfx
 move.l d1,d0

.bhfx:
 move.l d0,xxp_hztp(a0)    ;set horizontal slider to posn d0
 moveq #0,d0
 moveq #1,d1
 bsr TLScroll
 bra.s .booh

.upob:                     ;we are in up object...
 tst.w d3
 beq .null
 move.l xxp_vttp(a0),d0
 beq .null
 sub.l xxp_vstp(a0),d0
 bcc.s .bvfx
 moveq #0,d0
 bra.s .bvfx

.dnob:                     ;we are in down object...
 tst.w d3
 beq .null
 move.l xxp_vttt(a0),d1
 sub.l xxp_vtvs(a0),d1
 move.l xxp_vttp(a0),d0
 cmp.l d0,d1
 beq .null
 add.l xxp_vstp(a0),d0
 cmp.l d1,d0
 bls.s .bvfx
 move.l d1,d0

.bvfx:
 move.l d0,xxp_vttp(a0)    ;set vertical slider to posn d0
 moveq #0,d0
 moveq #-1,d1
 bsr TLScroll
 bra.s .boov

.horz:                     ;we are in horizontal object...
 move.l xxp_hztp(a0),d2
 moveq #-1,d0
 moveq #1,d1
 bsr.s TLScroll            ;get hztp value
 cmp.l xxp_hztp(a0),d2
 beq.s .null               ;null if didn't change
 bra.s .booh

.vert:                     ;we are in vertical object...
 move.l xxp_vttp(a0),d2
 moveq #-1,d0
 moveq #-1,d1
 bsr.s TLScroll            ;get vttp value
 cmp.l xxp_vttp(a0),d2
 beq.s .null               ;null if didn't change
 bra.s .boov

.booh:                     ;return d0 = +1 if horz changes
 addq.l #1,(a7)
 bra.s .null

.boov:                     ;return d0 = -1 if vert changes
 subq.l #1,(a7)

.null:                     ;return EQ, d0 = 0 if neither changes
 movem.l (a7)+,d0-d7/a0-a6
 tst.l d0
 rts


*>> set/get the scroller(s) of the active window

; D0=0 set, D0=-1 get         } if setting, load vttt..hstp and call
; D1=-1vert 0both +1horz      } if getting, result in vttp &/or hztp
; A0 = xxp_scro               }
; A5 = window                 }
; A6 = intuition.library base }

TLScroll:
 movem.l d0-d7/a0-a6,-(a7) ;save all
 move.l d1,d7              ;d7 = vert/both/horz
 move.l a0,a3              ;a3 = xxp_scro

 tst.l d0                  ;go if d0=-1 -> get
 bmi .get

 sub.w #28,a7              ;tags to set horizontal attributes

 tst.l d7                  ;go if vert only
 bmi.s .vert

 move.l a7,a0
 move.l #PGA_Top,(a0)+     ;tag 1: PGA_Top     = GA_Top
 move.l xxp_hztp(a3),(a0)+
 move.l #PGA_Total,(a0)+   ;tag 2: PGA_Total   = GA_Total
 move.l xxp_hztt(a3),(a0)+
 move.l #PGA_Visible,(a0)+ ;tag 3: PGA_Visible = GA_Visible
 move.l xxp_hzvs(a3),(a0)+
 clr.l (a0)

 move.l xxp_scoh(a3),a0    ;set horizontal attribs
 move.l a7,a1
 jsr _LVOSetAttrsA(a6)

 move.l xxp_scoh(a3),a0    ;refresh horizontal slider
 move.l a5,a1
 sub.l a2,a2
 moveq #1,d0
 jsr _LVORefreshGList(a6)

 tst.l d7                  ;go if vertical only
 bgt.s .pop

.vert:
 move.l a7,a0              ;tags to set vertical attributes
 move.l #PGA_Top,(a0)+     ;tag 1: PGA_Top     = GA_Top
 move.l xxp_vttp(a3),(a0)+
 move.l #PGA_Total,(a0)+   ;tag 2: PGA_Total   = GA_Total
 move.l xxp_vttt(a3),(a0)+
 move.l #PGA_Visible,(a0)+ ;tag 3: PGA_Visible = GA_Visible
 move.l xxp_vtvs(a3),(a0)+
 clr.l (a0)

 move.l xxp_scov(a3),a0    ;set vertical attribs
 move.l a7,a1
 jsr _LVOSetAttrsA(a6)

 move.l xxp_scov(a3),a0    ;refresh vertical slider
 move.l a5,a1
 sub.l a2,a2
 moveq #1,d0
 jsr _LVORefreshGList(a6)

.pop:                      ;finished setting
 add.w #28,a7
 bra.s .done

.get:                      ;here if get...
 tst.l d7
 bmi.s .gver               ;go if vert only

 move.l xxp_scoh(a3),a0
 move.l a3,a1
 add.w #xxp_hztp,a1
 move.l #PGA_Top,d0
 jsr _LVOGetAttr(a6)

 tst.l d7                  ;go if horz only
 bgt.s .done

.gver:
 move.l xxp_scov(a3),a0
 move.l a3,a1
 add.w #xxp_vttp,a1
 move.l #PGA_Top,d0
 jsr _LVOGetAttr(a6)

.done:
 movem.l (a7)+,d0-d7/a0-a6
 rts



*>> close a window opened with TLSOpenWindow

; TLSOpenWindow must have been successfully called
; After TLSCloseWindow the caller should call TLScrk

; a0 = the window returned by TLSOpenWind
; a6 = intuition.library base

TLSCloseWindow:
 movem.l d0-d1/a0-a1,-(a7) ;save all
 jsr _LVOCloseWindow(a6)
 movem.l (a7)+,d0-d1/a0-a1
 rts



*>> initialise xxp_slis structure

; a0 = screen for which xxp_slis made
; a3 = instance of an xxp_slis structure, as yet undefined
; a6 = intuition.library base

TLSlis:
 movem.l d0-d7/a0-a6,-(a7) ;save all

 clr.l xxp_szob(a3)
 clr.l xxp_draw(a3)

 moveq #pf_DoubleClick,d2  ;get xxp_psec,pmic from prefs
 sub.l d2,a7
 move.l a7,a0
 move.l d2,d0
 jsr _LVOGetPrefs(a6)
 move.l pf_KeyRptDelay+TV_SECS(a7),xxp_psec(a3)
 move.l pf_KeyRptDelay+TV_MICRO(a7),xxp_pmic(a3)
 move.l pf_KeyRptSpeed+TV_SECS(a7),xxp_dsec(a3)
 move.l pf_KeyRptSpeed+TV_MICRO(a7),xxp_dmic(a3)
 clr.l xxp_asec(a3)
 clr.l xxp_amic(a3)
 clr.w xxp_srpt(a3)
 add.l d2,a7

 sub.l #1000000,xxp_pmic(a3)  ;whole value to pmic,dmic
.mic1:
 add.l #1000000,xxp_pmic(a3)
 subq.b #1,xxp_psec+3(a3)
 bpl .mic1
 sub.l #1000000,xxp_dmic(a3)
.mic2:
 add.l #1000000,xxp_dmic(a3)
 subq.b #1,xxp_dsec+3(a3)
 bpl .mic2

 move.l 32(a7),a0          ;get screen draw info
 jsr _LVOGetScreenDrawInfo(a6)
 move.l d0,xxp_draw(a3)

 moveq #SIZEIMAGE,d0       ;size object
 bsr.s .Objt
 move.l d0,xxp_szob(a3)
 beq.s .bad
 moveq #LEFTIMAGE,d0       ;left object
 bsr.s .Objt
 move.l d0,xxp_lfob(a3)
 beq.s .bad
 moveq #RIGHTIMAGE,d0      ;right object
 bsr.s .Objt
 move.l d0,xxp_rtob(a3)
 beq.s .bad
 moveq #UPIMAGE,d0         ;up object
 bsr.s .Objt
 move.l d0,xxp_upob(a3)
 beq.s .bad
 moveq #DOWNIMAGE,d0       ;down object
 bsr.s .Objt
 move.l d0,xxp_dnob(a3)
 beq.s .bad
 moveq #CHECKIMAGE,d0      ;check object
 bsr.s .Objt
 move.l d0,xxp_ckob(a3)
 beq.s .bad

 moveq #-1,d0              ;quit ok
 bra.s .done

.bad:
 move.l 32(a7),a0
 bsr TLSlik                ;make structure undefined if bad
 moveq #0,d0

.done:
 move.l d0,(a7)            ;returns D0 = 0 if bad
 movem.l (a7)+,d0-d7/a0-a6
 rts

.Objt                      ;** create system image object,  D0 = which
 movem.l d1/a0-a2,-(a7)    ;save all except result in D0
 sub.l a0,a0               ;a0 = class = null
 lea .inam,a1              ;a1 = class name (since a0 null)
 sub.w #28,a7              ;room for 3 tags
 move.l a7,a2
 move.l #SYSIA_DrawInfo,(a2)+ ;tag 1: Draw Info
 move.l xxp_draw(a3),(a2)+
 move.l #SYSIA_Which,(a2)+    ;tag 2: Which = D0 on call
 move.l d0,(a2)+
 move.l #SYSIA_Size,(a2)+     ;tag 3: size = SYSISIZE_MEDRES
 move.l #SYSISIZE_MEDRES,(a2)+
 clr.l (a2)
 move.l a7,a2              ;a2 = tags
 jsr _LVONewObjectA(a6)    ;get object pointer
 add.w #28,a7              ;discard tags
 movem.l (a7)+,d1/a0-a2
 rts

.inam: dc.b "sysiclass",0
 ds.w 0



*>> clear an xxp_slis structure for which TLSlis has been called

; a0 = screen for which xxp_slis was attempted
; a3 = an instance of an xxp_slis structure, for which TLSlis has been
;      called, with or without success
; a6 = intuition.library base

TLSlik:
 movem.l d0-d7/a0-a6,-(a7) ;save all

 move.l xxp_szob(a3),d0    ;dispose of objects if any
 move.l d0,a0
 beq.s .draw
 jsr _LVODisposeObject(a6)
 move.l xxp_lfob(a3),d0
 move.l d0,a0
 beq.s .draw
 jsr _LVODisposeObject(a6)
 move.l xxp_rtob(a3),d0
 move.l d0,a0
 beq.s .draw
 jsr _LVODisposeObject(a6)
 move.l xxp_upob(a3),d0
 move.l d0,a0
 beq.s .draw
 jsr _LVODisposeObject(a6)
 move.l xxp_dnob(a3),d0
 move.l d0,a0
 beq.s .draw
 jsr _LVODisposeObject(a6)
 move.l xxp_ckob(a3),d0
 move.l d0,a0
 beq.s .draw
 jsr _LVODisposeObject(a6)

.draw:                     ;dispose of draw info if any
 move.l xxp_draw(a3),d0
 beq.s .done
 move.l 32(a7),a0
 move.l d0,a1
 jsr _LVOFreeScreenDrawInfo(a6)

.done:
 clr.l xxp_draw(a3)        ;flag xxp_slis as undefined
 clr.l xxp_szob(a3)
 movem.l (a7)+,d0-d7/a0-a6
 rts



*>> set up scrollers for a window

; a0 = screen
; a1 = gcnt (a so-far-undefined ds.l 1 to be used as gadget context)
; a2 = an xxp_slis structure for which TLSlis has been called
; a3 = a memory buffer of size xxp_scs2, which will initialised to
;      hold an instance of an xxp_scro object if TLScro is successful.
; a5 = gadtools.library base
; a6 = intuition.library base

TLScro:
 movem.l d0-d7/a0-a6,-(a7) ;save all exc result in d0

 move.l a2,xxp_scre(a3)
 move.l xxp_szob(a2),a0    ;set d7 = max ht of left, right, size objects
 moveq #0,d7
 move.w ig_Height(a0),d7
 move.l xxp_lfob(a2),a0
 cmp.w ig_Height(a0),d7
 bcc.s .mxh1
 move.w ig_Height(a0),d7
.mxh1:
 move.l xxp_rtob(a2),a0
 cmp.w ig_Height(a0),d7
 bcc.s .mxh2
 move.w ig_Height(a0),d7
.mxh2:

 moveq #0,d6               ;set d6 = max wd of up, down, size objects
 move.l xxp_szob(a2),a0
 move.w ig_Width(a0),d6
 move.l xxp_upob(a2),a0
 cmp.w ig_Width(a0),d6
 bcc.s .mxw1
 move.w ig_Width(a0),d6
.mxw1:
 move.l xxp_dnob(a2),a0
 cmp.w ig_Width(a0),d6
 bcc.s .mxw2
 move.w ig_Width(a0),d6
.mxw2:

 move.l 32(a7),a0          ;a0 = screen
 moveq #0,d4
 move.b sc_WBorTop(a0),d4
 move.l sc_Font(a0),a0
 add.w ta_YSize(a0),d4     ;d4 = screen top + font height + 1
 addq.w #1,d4

 sub.w #200,a7             ;make horizontal scroller object
 move.l a7,a1
 move.l #PGA_Freedom,(a1)+ ;tag 1: freedom = horizontal
 move.l #FREEHORIZ,(a1)+
 move.l #GA_LEFT,(a1)+     ;tag 2: left = 3
 move.l #3,(a1)+
 move.l #GA_RelBottom,(a1)+ ;tag 3: relbottom = 3 - D7
 moveq #3,d0
 sub.l d7,d0
 move.l d0,(a1)+
 move.l #GA_RelWidth,(a1)+ ;tag 4: relwidth = -(lfob wd + rtob wd + d6 +5)
 moveq #-5,d0
 sub.l d6,d0
 moveq #0,d1
 move.l xxp_lfob(a2),a0
 move.w ig_Width(a0),d1
 move.l xxp_rtob(a2),a0
 add.w ig_Width(a0),d1
 sub.l d1,d0
 move.l d0,(a1)+
 move.l #GA_Height,(a1)+   ;tag 5: height = d7 - 4
 move.l d7,d0
 subq.l #4,d0
 move.l d0,(a1)+
 move.l #GA_BottomBorder,(a1)+  ;tag 6: bottom border = 1
 move.l #1,(a1)+
 move.l #GA_ID,(a1)+       ;tag 7: id = 50
 move.l #50,(a1)+
 move.l #PGA_Total,(a1)+   ;tag 8: total = 256 pro-tem
 move.l #256,(a1)+
 move.l #256,xxp_hztt(a3)
 move.l #PGA_Visible,(a1)+ ;tag 9: visible = 256 pro-tem
 move.l #256,(a1)+
 move.l #256,xxp_hzvs(a3)
 move.l #PGA_Top,(a1)+     ;tag 10: top = 0 pro-tem
 clr.l (a1)+
 clr.l xxp_hztp(a3)
 move.l #1,xxp_hstp(a3)
 move.l #PGA_Borderless,(a1)+   ;tag 11: borderless = 1
 move.l #1,(a1)+
 move.l #ICA_TARGET,(a1)+  ;tag 12: target = ictarget
 move.l #ICTARGET_IDCMP,(a1)+
 move.l #PGA_NewLook,(a1)+ ;tag 13 newlook = true
 move.l #1,(a1)+
 clr.l (a1)

 sub.l a0,a0               ;ready to create
 lea .gcls,a1
 move.l a2,d5
 move.l a7,a2
 jsr _LVONewObjectA(a6)
 add.w #200,a7
 move.l d5,a2
 move.l d0,xxp_scoh(a3)
 beq .bad2a                ;bad if can't

 sub.w #200,a7             ;make "<" button
 move.l a7,a1

 move.l #GA_Image,(a1)+    ;tag 1: image = lfob
 move.l xxp_lfob(a2),(a1)+
 move.l #GA_RelRight,(a1)+ ;tag 2: rel right = -(lfob wd + rtob wd + d6 - 1)
 moveq #1,d0
 moveq #0,d1
 move.l xxp_lfob(a2),a0
 move.w ig_Width(a0),d1
 move.l xxp_rtob(a2),a0
 add.w ig_Width(a0),d1
 sub.l d1,d0
 sub.l d6,d0
 move.l d0,(a1)+
 move.l #GA_RelBottom,(a1)+ ;tag 3: rel bottom = -(lfob ht -1)
 moveq #1,d0
 moveq #0,d1
 move.l xxp_lfob(a2),a0
 move.w ig_Height(a0),d1
 sub.l d1,d0
 move.l d0,(a1)+
 move.l #GA_BottomBorder,(a1)+ ;tag 4: bottom border = 1
 move.l #1,(a1)+
 move.l #GA_Previous,(a1)+  ;tag 5: previous = slider ob
 move.l xxp_scoh(a3),(a1)+
 move.l #GA_ID,(a1)+        ;tag 6: id = 51
 move.l #51,(a1)+
 move.l #ICA_TARGET,(a1)+   ;tag 7: target = idcmp
 move.l #ICTARGET_IDCMP,(a1)+
 clr.l (a1)

 sub.l a0,a0               ;ready make "<" button
 lea .bcls,a1
 move.l a2,d5
 move.l a7,a2
 jsr _LVONewObjectA(a6)
 add.w #200,a7
 move.l d5,a2
 move.l d0,xxp_slfo(a3)
 beq .bad2b                ;bad of can't

 sub.w #200,a7             ;make ">" button
 move.l a7,a1

 move.l #GA_Image,(a1)+    ;tag 1: image = right object
 move.l xxp_rtob(a2),(a1)+
 move.l #GA_RelRight,(a1)+ ;tag 2: rel right = -(rtob wd + d6 - 1)
 moveq #1,d0
 moveq #0,d1
 move.l xxp_rtob(a2),a0
 move.w ig_Width(a0),d1
 add.l d6,d1
 sub.l d1,d0
 move.l d0,(a1)+
 move.l #GA_RelBottom,(a1)+ ;tag 3: rel bottom = -(rtob ht - 1)
 moveq #1,d0
 moveq #0,d1
 move.l xxp_rtob(a2),a0
 move.w ig_Height(a0),d1
 sub.l d1,d0
 move.l d0,(a1)+
 move.l #GA_BottomBorder,(a1)+ ;tag 4: bottom border = 1
 move.l #1,(a1)+
 move.l #GA_Previous,(a1)+ ;tag 5: previous = left gadget
 move.l xxp_slfo(a3),(a1)+
 move.l #GA_ID,(a1)+       ;tag 6: id = 52
 move.l #52,(a1)+
 move.l #ICA_TARGET,(a1)+  ;tag 7: target = idcmp
 move.l #ICTARGET_IDCMP,(a1)+
 clr.l (a1)

 sub.l a0,a0               ;ready to make ">" button
 lea .bcls,a1
 move.l a2,d5
 move.l a7,a2
 jsr _LVONewObjectA(a6)
 add.w #200,a7
 move.l d5,a2
 move.l d0,xxp_srto(a3)
 beq .bad2c                ;bad if can't

 sub.w #200,a7             ;make vertical scroller
 move.l a7,a1

 move.l #PGA_Freedom,(a1)+ ;tag 1: freedom = vertical
 move.l #FREEVERT,(a1)+
 move.l #GA_Top,(a1)+      ;tag 2: top = d4 + 1
 move.l d4,d0
 addq.l #1,d0
 move.l d0,(a1)+
 move.l #GA_RelRight,(a1)+ ;tag 3: rel right = -(d6 - 4)
 moveq #4,d0
 sub.l d6,d0
 addq.l #1,d0              ;why needed?????????????
 move.l d0,(a1)+
 move.l #GA_RelHeight,(a1)+ ;tag 4: rel height = -(sz+up+dn ht + 2 + d4)
 moveq #-2,d0
 moveq #0,d1
 move.l xxp_szob(a2),a0
 move.w ig_Height(a0),d1
 move.l xxp_upob(a2),a0
 add.w ig_Height(a0),d1
 move.l xxp_dnob(a2),a0
 add.w ig_Height(a0),d1
 sub.l d1,d0
 sub.l d4,d0
 move.l d0,(a1)+
 move.l #GA_Width,(a1)+    ;tag 5: width = d6 - 6
 move.l d6,d0
 subq.l #6,d0
 subq.l #2,d0              ;why needed ?????????
 move.l d0,(a1)+
 move.l #GA_RightBorder,(a1)+ ;tag 6: right border = 1
 move.l #1,(a1)+
 move.l #GA_ID,(a1)+       ;tag 7: id = 53
 move.l #53,(a1)+
 move.l #PGA_Total,(a1)+   ;tag 8: total = 256
 move.l #256,(a1)+
 move.l #256,xxp_vttt(a3)
 move.l #PGA_Visible,(a1)+ ;tag 9: visible = 256
 move.l #256,(a1)+
 move.l #256,xxp_vtvs(a3)
 move.l #PGA_Top,(a1)+     ;tag 10: top = 0
 clr.l (a1)+
 clr.l xxp_vttp(a3)
 move.l #1,xxp_vstp(a3)
 move.l #PGA_Borderless,(a1)+   ;tag 11: borderless = 1
 move.l #1,(a1)+
 move.l #ICA_TARGET,(a1)+  ;tag 12: target = idcmp
 move.l #ICTARGET_IDCMP,(a1)+
 move.l #PGA_NewLook,(a1)+ ;tag 13 newlook = true
 move.l #1,(a1)+
 clr.l (a1)

 sub.l a0,a0               ;ready to make vertical slider
 lea .gcls,a1
 move.l a2,d5
 move.l a7,a2
 jsr _LVONewObjectA(a6)
 add.w #200,a7
 move.l d5,a2
 move.l d0,xxp_scov(a3)
 beq .bad2d                ;bad if can't

 sub.w #200,a7             ;make "^" button
 move.l a7,a1

 move.l #GA_Image,(a1)+    ;tag 1: image = up object
 move.l xxp_upob(a2),(a1)+
 move.l #GA_RelRight,(a1)+ ;tag 2: rel right = -(upob wd - 1)
 moveq #1,d0
 moveq #0,d1
 move.l xxp_upob(a2),a0
 move.w ig_Width(a0),d1
 sub.l d1,d0
 move.l d0,(a1)+
 move.l #GA_RelBottom,(a1)+    ;tag 3: rel bottom = -(up+dn+sz ob - 1)
 moveq #1,d0
 moveq #0,d1
 move.l xxp_upob(a2),a0
 move.w ig_Height(a0),d1
 move.l xxp_dnob(a2),a0
 add.w ig_Height(a0),d1
 move.l xxp_szob(a2),a0
 add.w ig_Height(a0),d1
 sub.l d1,d0
 move.l d0,(a1)+
 move.l #GA_RightBorder,(a1)+  ;tag 4: right border = 1
 move.l #1,(a1)+
 move.l #GA_Previous,(a1)+ ;tag 5: previous = vert slider
 move.l xxp_scov(a3),(a1)+
 move.l #GA_ID,(a1)+       ;tag 6: id = 54
 move.l #54,(a1)+
 move.l #ICA_TARGET,(a1)+  ;tag 7: target = idcmp
 move.l #ICTARGET_IDCMP,(a1)+
 clr.l (a1)

 sub.l a0,a0               ;ready to make "^" button
 lea .bcls,a1
 move.l a2,d5
 move.l a7,a2
 jsr _LVONewObjectA(a6)
 add.w #200,a7
 move.l d5,a2
 move.l d0,xxp_supo(a3)
 beq .bad2e                ;bad if can't

 sub.w #200,a7             ;make "v" button
 move.l a7,a1

 move.l #GA_Image,(a1)+    ;tag 1: image = down object
 move.l xxp_dnob(a2),(a1)+
 move.l #GA_RelRight,(a1)+ ;tag 2: rel right = -(dnob wd - 1)
 moveq #1,d0
 moveq #0,d1
 move.l xxp_dnob(a2),a0
 move.w ig_Width(a0),d1
 sub.l d1,d0
 move.l d0,(a1)+
 move.l #GA_RelBottom,(a1)+    ;tag 3: rel bottom = -(dn+sz ob ht -1)
 moveq #1,d0
 moveq #0,d1
 move.l xxp_dnob(a2),a0
 move.w ig_Height(a0),d1
 move.l xxp_szob(a2),a0
 add.w ig_Height(a0),d1
 sub.l d1,d0
 move.l d0,(a1)+
 move.l #GA_RightBorder,(a1)+  ;tag 4: right border = 1
 move.l #1,(a1)+
 move.l #GA_Previous,(a1)+ ;tag 5: previous = ^ button
 move.l xxp_supo(a3),(a1)+
 move.l #GA_ID,(a1)+       ;tag 6: id = 55
 move.l #55,(a1)+
 move.l #ICA_TARGET,(a1)+  ;tag 7: target = idcmp
 move.l #ICTARGET_IDCMP,(a1)+
 clr.l (a1)

 sub.l a0,a0               ;ready to make "v" object
 lea .bcls,a1
 move.l a2,d5
 move.l a7,a2
 jsr _LVONewObjectA(a6)
 add.w #200,a7
 move.l d5,a2
 move.l d0,xxp_sdno(a3)
 beq .bad2f                ;bad if can't

 move.l 36(a7),a0          ;create gadget object
 clr.l (a0)
 exg a5,a6
 jsr _LVOCreateContext(a6)
 exg a5,a6

 tst.l d0
 beq .bad2g                ;bad if can't

 move.l d0,a0              ;daisy chain gadgets together...
 move.l a0,xxp_gcnt(a3)
 move.l gg_NextGadget(a0),d0 ;a0 = start gadget; d0 = gadget delimiter

 move.l xxp_scoh(a3),a2      ;start gad -> horiz scroller
 move.l a2,gg_NextGadget(a0)
 move.l a2,a0
 move.l xxp_slfo(a3),a2      ;horiz slider -> left button
 move.l a2,gg_NextGadget(a0)
 move.l a2,a0
 move.l xxp_srto(a3),a2      ;left button -> right button
 move.l a2,gg_NextGadget(a0)
 move.l a2,a0
 move.l xxp_scov(a3),a2      ;vert slider -> right button
 move.l a2,gg_NextGadget(a0)
 move.l a2,a0
 move.l xxp_supo(a3),a2      ;up button -> vert slider
 move.l a2,gg_NextGadget(a0)
 move.l a2,a0
 move.l xxp_sdno(a3),a2      ;down button -> up button
 move.l a2,gg_NextGadget(a0)
 move.l a2,a0
 move.l d0,gg_NextGadget(a0) ;terminator -> down button

 moveq #-1,d0              ;return good
 bra.s .done

.bad1:
 bra.s .bad

.bad2g:
 move.l xxp_sdno(a3),a0
 jsr _LVODisposeObject(a6)
.bad2f:
 move.l xxp_supo(a3),a0
 jsr _LVODisposeObject(a6)
.bad2e:
 move.l xxp_scov(a3),a0
 jsr _LVODisposeObject(a6)
.bad2d:
 move.l xxp_srto(a3),a0
 jsr _LVODisposeObject(a6)
.bad2c:
 move.l xxp_slfo(a3),a0
 jsr _LVODisposeObject(a6)
.bad2b:
 move.l xxp_scoh(a3),a0
 jsr _LVODisposeObject(a6)
.bad2a:

.bad:
 clr.l xxp_scoh(a3)        ;flag xxp_scro undefined if bad
 moveq #0,d0

.done:
 move.l d0,(a7)            ;returns D0 = 0 if bad
 movem.l (a7)+,d0-d7/a0-a6
 rts

.gcls: dc.b "propgclass",0
.bcls: dc.b "buttongclass",0
  ds.w 0



*>> free an xxp_scro structure for whch TLScro has been called

; a3 = window's xxp_scro
; a5 = gadtools.library base
; a6 = intuition.library base

; OK to call if TLScro failed

TLScrk:
 movem.l d0-d7/a0-a6,-(a7)

 tst.l xxp_scoh(a3)        ;go if undefined
 beq.s Sk_done

 moveq #5,d2               ;free scroller objects in window's xxp_scro
 move.l a3,a2
.frob:
 move.l (a2)+,a0
 jsr _LVODisposeObject(a6)
 dbra d2,.frob

 move.l xxp_gcnt(a3),a0
 clr.l gg_NextGadget(a0)
 exg a5,a6
 jsr _LVOFreeGadgets(a6)
 exg a5,a6

Sk_done:
 clr.l xxp_scoh(a3)        ;flag as undefined

 movem.l (a7)+,d0-d7/a0-a6
 rts


 ENDC                      ;end of TLS_Stuff
