[comp.binaries.apple2] tn.iigs.074

mjohnson@APPLE.COM (Mark B. Johnson) (12/02/89)

This message  was originally  submitted by  mjohnson@APPLE.COM to  the APPLE2-L
list  at BROWNVM.  If  you simply  forward  it back  to the  list,  it will  be
distributed with the paragraph you are now reading being automatically removed.
If you  edit the  contributions you  receive into  a digest,  you will  need to
remove this  paragraph before mailing the  result to the list.  Finally, if you
need more information from the author of this message, you should be able to do
so by simply replying to this note.

----------------- Message requiring your approval (155 lines) -----------------
Apple II
Technical Notes
_____________________________________________________________________________
                                                  Developer Technical Support


Apple IIGS
#74:    A Faster List Manager Draw Routine

Written by:    Jim Mensch                                       November 1989

This Technical Note presents a method for speeding up custom List Draw
routines, with sample source code for the APW assembler.
_____________________________________________________________________________


The List Manager is designed to allow users to select from relatively small
lists.  In this respect, it does quite well.  However, when the width or
height of the displayed area gets above a certain size (about 20 chars wide
and 6 items tall) the list starts to scroll slower than normal.  This is due
to the design of the List Manager's scroll routine.  To scroll text, the List
Manager calls ScrollRect to scroll the list, then it  redraws all the visible
members.  On small lists this is fine, but on larger lists it can cause the
redrawing of much data that is already on the screen, which can take time.  To
cure this problem, you can include a simple draw procedure in your program
that checks the clipRgn before anything is drawn.  This way, you will not
attempt to redraw items that do not need redrawing.

The custom draw routine in this Note is an example of one such routine that
could be used.  It first checks the current clipRgn  (which the List Manager
was kind enough to shrink down to include only the portion of the list that
needs redrawing) against the passed item rectangle.  If the rectangle is in
any way enclosed in the clipRgn, then the member is redrawn; otherwise the
routine simply returns to the List Manager without drawing.  This sample
routine is designed to work only with Pascal-style strings, but it can be
easily modified to use any other type of string you choose.

MyListDraw Start
;
; This routine draws a list member if any part of the member's
; rectangle is inside the current clipRgn.
;
; Note that the Data Bank register is not defined on entry
; to this routine.  If you use any absolute addressing, you
; must set B yourself and restore its value before exiting.
;
top        equ    0
left       equ    top+2
bottom     equ    left+2
right      equ    bottom+2
rgnBounds  equ    2
;
oldDPage   equ    1
theRTL     equ    oldDPage+2
listHand   equ    theRTL+3
memPtr     equ    listHand+4
theRect    equ    memPtr+4
           using  globals

           phd
           tsc
           tcd

           pha
           pha
           _GetClipHandle
           PullLong listHand

           ldy    #2
           lda    [listhand],y
           tax
           lda    [listhand]
           sta    listhand
           stx    listhand+2

           lda    [therect]         ; now test the top
           dec    a                 ; adjust and give a little slack
           ldy    #rgnbounds+bottom
           cmp    [listhand],y      ; rgnRectBottom>=top?
           blt    skip2
           brl    NoDraw            ; if not don't draw..
Skip2      ldy    #bottom           ; now see if the bottom is higher than
                                    ; the top
           inc    a                 ; give a little slack
           lda    [therect],y
           ldy    #rgnBounds+top
           cmp    [listhand],y
           blt    NoDraw
NoTest    ANOP

           PushLong theRect
           _EraseRect               ; erase the old rectangle

           ldy    #left
           lda    [theRect],y
           tax
           ldy    #bottom
           lda    [theRect],y
           dec    a
           phx
           pha
           _MoveTo
           ldy    #2
           lda    [memptr],y
           pha
           lda    [memptr]
           pha
           _DrawString

           ldy    #4
           lda    [memPtr],y
           and    #$00C0            ; strip to the 6 and 7 bits
           beq    memDrawn          ; if they are both 0 the member is drawn
           cmp    #$0080            ; member selected?
           bne    noSelect          ; member not selectable
           PushLong theRect
           _InvertRect
           bra    memDrawn
; if we get here the member is disabled
noSelect   PushLong #DimMask
           _SetPenMask
           PushLong theRect
           _EraseRect
           PushLong #NorMask
           _SetPenMask
memDrawn   ANOP


; exit here
           pld
           sep    #$20
           longa  off
           pla
           ply

           plx
           plx
           plx
           plx
           plx
           plx
           phy
           pha
           rep    #$20
           longa  on
           rtl

DimMask    dc     i1'$55,$AA,$55,$AA,$55,$AA,$55,$AA'
NorMask    dc     i1'$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF'
           end


Further Reference
_____________________________________________________________________________
    o    Apple IIGS Toolbox Reference, Volumes 1 and 3