;----------------------------------------------------------- ; ; Api92/Api89 Source Code ; ; (c) NeXO Software, Benoit SCHERRER ; e-mail : p.c.scherrer@wanadoo.fr ; ; ; File> listview.xas ; Utility> A complete universal listview ; component (with scrolling) ; ;----------------------------------------------------------- LV_STRUCTSIZE equ $28 LV_NBITEM equ $00 LV_NBITEMPP equ $02 LV_X equ $04 LV_Y equ $06 LV_RESERVED1 equ $08 LV_RESERVED2 equ $0A LV_WIDTH equ $0C LV_CSTSIZE equ $0E LV_ITEMHEIGHT equ $10 LV_FLAG equ $12 LV_CBKEYDOWN equ $14 LV_CBKEY equ $18 LV_CBSELECT equ $1C LV_CBDRAWITEM equ $20 LV_ITEMPROP equ $24 ;----------------------------------------------------- ;Input> a0.l : Address of a api92ListView structure ; a1.l : Address of data ;Out> d0.w : - if api92CallBack_Key=0, d0.w=#264 if ESC ; or #13 if ENTER ; - Else d0.w is the exit value given in the ; api92CallBack_Key function ; d1.w : If api92CallBack_Key<>0, d1.w is the last ; value given in the api92CallBack_Key function ; a0.l : The address of the select item ; ;Format of the api92ListView structure : ; $00.w : Number of items ; $02.w : Number of items per page ; $04.w : X position ; $06.w : Y position ; $08.w : reserved (must be 0) ; $0A.w : reserved (must be 0) ; $0C.w : Width of the Listview component ; $0E.w : If not null, specify a constant ; size for each item. Else each item ; must be zero terminated ; $10.w : If not null, specify a constant height ; for each item ; $12.b : Flags ; $13.b : Nothing ; $14.l : If not null, address of an ; api92CB_lvKeyDown function ; $18.l : If not null, address of an ; api92CB_lvKey function ; $1C.l : If not null, address of an ; api92CB_lvOnSelect ; $20.l : If not null, address of an ; api92CallBack_lvDrawItem function ; $24.l : Address of an api92_lvItemsProperties ; buffer ; ; Flags : ; xxxxxxx1 : If set don't draw the rect ; xxxxxx1x : If set allow the user to jump from the ; first item to the last with up ; xxxxx1xx : If set, keep the previous selected item ; 1xxxxxxx : If set, only draw listview component ; x1xxxxxx : If set, draw a vertical scroll bar ; api92_lvItemsProperties : ; This buffer is an array of one byte for each item. ; Each byte describe the properties of the item. It ; has the following format : ; xxxxxxxO : Enabled (1) / Disabled (0) bit ; xxxxxxOx : Use Checkbox (1) ; xxxxxOxx : Checked (1) / Unchecked (0) bit ; ;----------------------------------------------------- ;api92CallBack_lvDrawItem: ;Input> d0.w : X position ; d1.w : Y position ; d6.w : 0-based index of current item ; a1.l : Address of current item string ; a6.l : Address of the api92ListView structure ; used ;Out> d0.w : If d0.w = 0 : don't use internal drawing ; of the item ; If d0.w = 1 : use internal drawing of the ; item ;----------------------------------------------------- ;api92CallBack_lvKeys: ;Input> d0.w : ScanCode of key pressed ; d6.w : 0-based index of selected item ; a1.l : Address of selected item string ; a6.l : Address of the api92ListView structure ; used ;Out> d0.w : If d0.w = 0 : continue ; If d0.w = $FFFF : Redraw component ; Else exit component with d0 and d1 ; values ;----------------------------------------------------- ;api92CB_lvKeyDown: ;Input> d0.w : ScanCode of key pressed ; d6.w : 0-based index of selected item ; a1.l : Address of selected item string ; a6.l : Address of the api92ListView structure ; used ;----------------------------------------------------- SF_SIZE equ 6 SF_FONTHEIGHT equ 0 SF_NBITEM equ 2 SF_NBITEMPP equ 4 apilib@0044: _ListViewComponent: movem.l d2-d7/a1-a6,-(a7) move.l a0,a6 ;Save address move.l a1,a4 suba.w #SF_SIZE,a7 ;Create a stack frame move.l a7,a5 clr.w d6 clr.w d7 btst.b #2,LV_FLAG(a6) ;Save position ? beq.s \NoSave move.w LV_RESERVED1(a6),d6 move.w LV_RESERVED2(a6),d7 \NoSave move.w (a6),SF_NBITEM(a5) ;Nb Item in SF move.w LV_NBITEMPP(a6),SF_NBITEMPP(a5) subq.w #1,SF_NBITEM(a5) subq.w #1,SF_NBITEMPP(a5) move.w LV_ITEMHEIGHT(a6),d0 ;ItemHeight Definited ? beq.s \noheight move.w d0,SF_FONTHEIGHT(a5) ; bra.s \RdLoop \noheight bsr _GetFontWidthHeight ;if not, get font size addq.w #1,d1 ;Add 1 to the height move.w d1,SF_FONTHEIGHT(a5) \RdLoop bsr _DrawListView ;Draw the list view bsr _lvSelectItem ;select current item btst.b #7,LV_FLAG(a6) ;flag=just show list ? bne \Exit \Loop btst.b #6,LV_FLAG(a6) ;flag=show scroll bar ? beq.s \noscrollbar suba.w #16,a7 ;create a stack frame for the structure move.l a7,a0 ;save its addr move.w d6,(a0)+ ;CurrentValue=Current Item move.w LV_X(a6),d0 add.w LV_WIDTH(a6),d0 move.w d0,(a0)+ ;X pos move.w LV_Y(a6),(a0)+ ;Y pos move.w LV_NBITEMPP(a6),d0 ;Height=NbItemPerPage*height mulu.w SF_FONTHEIGHT(a5),d0 ; addq.w #3,d0 move.w d0,(a0)+ ;Height move.w SF_NBITEM(a5),(a0)+ ;MaxValue move.w #5,(a0)+ ;Height of the bar move.l a7,a0 bsr _VScrollComponent ;Draw ScrollBar Component add.w #16,a7 \noscrollbar bsr _WaitKey ;Wait for a key movem.l d2-d7/a1-a6,-(a7) move.l LV_CBKEYDOWN(a6),a0 ;Get address of Key function move.l a0,d1 beq.s \skip2 ;Test if null move.l d0,-(a7) ;Save Key move.w d6,d0 ;Get Item addr for function move.l d6,d0 bsr GetItemAddr ; in a1 move.l (a7)+,d0 ;Restore Key jsr (a0) ;Call CB function \skip2 movem.l (a7)+,d2-d7/a1-a6 cmp.w #PAD_DOWN,d0 beq \down cmp.w #PAD_UP,d0 beq \up move.w d0,d2 ;Save d0=key code movem.l d2-d7/a1-a6,-(a7) move.l LV_CBKEY(a6),a0 ;Get address of Key function move.l a0,d1 bne.s \CB_Key ;Test if null move.w d6,d1 ;index of slcted item cmp.w #264,d0 ;If null, ESC ? beq.s \skip ;And if ESC, exit LV component cmp.w #13,d0 ;ENTER ? beq.s \skip clr.w d0 ;else continue bra.s \skip \CB_Key move.l d0,-(a7) ;Save Key move.w d6,d0 ;Get Item addr for function bsr GetItemAddr ; in a1 move.l (a7)+,d0 ;Restore Key jsr (a0) ;Call function \skip movem.l (a7)+,d2-d7/a1-a6 cmp.w #13,d2 ;Key =ENTER ? bne.s \no_check move.l LV_ITEMPROP(a6),a2 ;lvItemsProperties buffer move.l a2,d2 ;null ? beq.s \no_check adda.w d6,a2 btst.b #1,(a2) ;CheckBox item ? beq.s \no_check bchg.b #2,(a2) ;if yes, swap checked bra \RdLoop \no_check cmp.w #$FFFF,d0 ;if d0=$FFFF beq \RdLoop ; redraw component tst.w d0 ;else loop beq \Loop \Exit move.w d6,LV_RESERVED1(a6) move.w d7,LV_RESERVED2(a6) move.l d0,-(a7) move.w d6,d0 bsr GetItemAddr move.l a1,a0 move.l (a7)+,d0 adda.w #SF_SIZE,a7 ;Delete stack frame movem.l (a7)+,d2-d7/a1-a6 rts \up tst.w d6 ;test first item ? bne.s \notfirst btst.b #1,LV_FLAG(a6) ;flag= beq.s \noup move.w SF_NBITEM(a5),d6 move.w SF_NBITEMPP(a5),d7 cmp.w d7,d6 bhi.s \draw1 move.w SF_NBITEM(a5),d7 bra.s \draw1 \notfirst bsr _lvSelectItem ;deselect item subq.w #1,d6 tst.w d7 bne.s \noscroll \draw1 bsr _DrawListView addq.l #1,d7 \noscroll subq.w #1,d7 bsr _lvSelectItem move.w d6,d0 bsr GetItemAddr cmp.b #'-',(a1) beq.s \up bsr Call_CBSelect \noup bra \Loop \down cmp.w SF_NBITEM(a5),d6 ;Compare with NbItem-1 bne.s \notlast btst.b #1,LV_FLAG(a6) beq.s \nodown clr.w d6 clr.w d7 bra.s \draw2 \notlast bsr _lvSelectItem ;deselect item addq.w #1,d6 cmp.w SF_NBITEMPP(a5),d7 bne.s \noscoll \draw2 bsr _DrawListView subq.w #1,d7 \noscoll addq.w #1,d7 bsr _lvSelectItem move.w d6,d0 bsr GetItemAddr cmp.b #'-',(a1) beq.s \down bsr Call_CBSelect \nodown bra \Loop Call_CBSelect: movem.l d0-d7/a1-a6,-(a7) move.l LV_CBSELECT(a6),a0 ;Get address of Key function move.l a0,d1 beq.s \exit ;Test if null move.w d6,d0 ;Get Item addr for function bsr GetItemAddr ; in a1 jsr (a0) ;Call function \exit movem.l (a7)+,d0-d7/a1-a6 rts ;--------------------------------- ; Draw the listview ;--------------------------------- _DrawListView move.w #$500,d0 trap #1 move.l d0,-(a7) move.l d6,-(a7) move.w LV_Y(a6),-(a7) ;Push Y move.w LV_NBITEMPP(a6),d0 ;NbItemPerPage mulu.w SF_FONTHEIGHT(a5),d0 ; add.w d0,(a7) addq.w #2,(a7) ;Y2 is now on the stack move.w LV_X(a6),d0 ;X add.w LV_WIDTH(a6),d0 ;Add Width move.w d0,-(a7) ;X2 is on the stack move.w LV_Y(a6),-(a7) ;Y move.w LV_X(a6),-(a7) ;X bsr _draw_EraseRect btst.b #0,LV_FLAG(a6) ;Test bit 0 of flags bne.s \norect ;If set don't draw the rect bsr _draw_FrameRect \norect addq.l #8,a7 move.w d6,d0 ; sub.w d7,d0 ;d0=Address of first item move.w d0,d6 ;First item bsr GetItemAddr ;Return in a1 addr item d0 move.l LV_ITEMPROP(a6),a2 ;lvItemsProperties buffer adda.w d0,a2 move.w (a6),d3 ;d3=NbItems sub.w d0,d3 ;substract first item index cmp.w LV_NBITEMPP(a6),d3 ;Compare with NbItemPerPage bcs.s \skip move.w LV_NBITEMPP(a6),d3 \skip tst.w d3 beq \exit subq.w #1,d3 move.w LV_X(a6),d0 ;X move.w LV_Y(a6),d1 ;Y addq.w #2,d0 addq.w #2,d1 ; clr.l d6 ;Item index \draw cmp.b #'-',(a1) bne.s \NoLine move.l d1,-(a7) ;Save original Y move.w SF_FONTHEIGHT(a5),d2 ;Calc lsr.w #1,d2 ; Height/2 add.w d2,d1 move.w LV_WIDTH(a6),d2 ;Width subq.w #4,d2 bsr _draw_HorizontalLine move.l (a7)+,d1 bra \skip2 \NoLine movem.l d0-d7/a0-a6,-(a7) move.l LV_CBDRAWITEM(a6),a0 ;Get address of function cmp.l #0,a0 ;DrawItem support ? beq.s \idraw jsr (a0) ;Call function tst.w d0 ;Use internal drawing ? bne.s \idraw ;if <>0, yes movem.l (a7)+,d0-d7/a0-a6 ;else... bra.s \skip2 \idraw movem.l (a7)+,d0-d7/a0-a6 \noDraw cmp.l #0,LV_ITEMPROP(a6) ;lvItemProperties support ? beq.s \NoLvItemsProp btst.b #1,(a2) beq.s \NoChkBox1 lea CheckBoxes(PC),a0 move.l d1,-(a7) move.w SF_FONTHEIGHT(a5),d2 subq.w #6,d2 lsr.w #1,d2 add.w d2,d1 moveq.w #4,d2 ;NbLine-1 btst.b #2,(a2) beq.s \CheckON addq.l #5,a0 \CheckON bsr _draw_GFX8xn move.l (a7)+,d1 \NoChkBox1 movem.l d0-d2/a0-a1,-(a7) move.w #4,-(a7) btst.b #0,(a2) bne.s \Enabled move.w #3,(a7) \Enabled move.l a1,-(a7) move.w d1,-(a7) move.w d0,-(a7) btst.b #1,(a2) beq.s \NoChkBox addq.w #8,(a7) \NoChkBox TIOS_CALL DrawStrXY lea 10(a7),a7 movem.l (a7)+,d0-d2/a0-a1 bra.s \skip2 \NoLvItemsProp bsr _draw_StringSpecial \skip2 add.w SF_FONTHEIGHT(a5),d1 addq.l #1,a2 ;next lvItemsProperties move.w LV_CSTSIZE(a6),d2 ;Constant size ? beq.s \skip3 ;if null, not adda.w d2,a1 ;else, ok bra.s \skip4 \skip3 tst.b (a1)+ bne.s \skip3 \skip4 addq.l #1,d6 ;Increment item index dbra.s d3,\draw \exit move.l (a7)+,d6 move.l (a7)+,d0 trap #1 rts ;--------------------------------- ; Select an item ;--------------------------------- _lvSelectItem: movem.l d0-d3/d7,-(a7) move.w LV_X(a6),d0 ;X move.w LV_Y(a6),d1 ;Y addq.w #1,d0 addq.w #1,d1 mulu.w SF_FONTHEIGHT(a5),d7 add.w d7,d1 move.w LV_WIDTH(a6),d2 ;Width subq.w #1,d2 move.w SF_FONTHEIGHT(a5),d3 bsr _InvertArea movem.l (a7)+,d0-d3/d7 rts ;--------------------------------- ;Input> d0.w : Index of item ;Out> a1.l : Address of item ;--------------------------------- GetItemAddr movem.l d0/d1,-(a7) move.l a4,a1 ;Address of data tst.w d0 ; beq.s \exit ;if first item, exit move.w LV_CSTSIZE(a6),d1 beq.s \NoConstantSize mulu.w d1,d0 ; adda.w d0,a1 bra.s \exit \NoConstantSize subq.w #1,d0 ;for dbra \NextItem tst.b (a1)+ bne.s \NextItem dbra.s d0,\NextItem \exit movem.l (a7)+,d0/d1 rts