home *** CD-ROM | disk | FTP | other *** search
/ HomeWare 14 / HOMEWARE14.bin / utils2 / mymous12.arj / SCREENTA.ASM < prev   
Assembly Source File  |  1994-01-07  |  10KB  |  224 lines

  1. ; MyMouse
  2. ; Bit to handle screen-activewindow associative table
  3. ; Andrew Forrest
  4. ;****************************************************************************
  5. ; The program manages the table as a linked list of blocks. Each block
  6. ; contains up to a maximum number of (screen, activewindow) pairs. The head
  7. ; of the list is the most recently-accessed pair.
  8. ; All these routines should be called with Intuitionbase locked.
  9. ; No arbitration is done for access to screen table, so only one task at a
  10. ; time please.
  11. ;***************************************************************************
  12. ; USES:
  13. ;    Globals.ScreenTable    (the abstract object itself)
  14. ; EXPORTS:
  15. ;    InitialiseScreenTable()    ; Call this first
  16. ;    ShutDownScreenTable()    ; Call this last
  17. ;    AssociateWindow(Screen, Window)    ; Insert a tuple in the table
  18. ;    IndexScreenTable(Screen) : Window    ; Look up a tuple
  19. ;    PruneScreenTable()    ; Remove redundant entries
  20. ;    
  21. ;***************************************************************************
  22. ; Table is represented as a linked list of blocks, each with up to
  23. ; TuplesPerChunk tuples. (Each chunk in the table is an Exec minnode.)
  24.  
  25. ; The last chunk may be partially-empty, in which case the remaining spaces 
  26. ; are filled with NULL screen pointers. It is vitally important (to 
  27. ; PruneScreenTable()) that _only_ the last node is padded with NULLs. 
  28. ; ScreenTable.LastTupleOffset is the offset (from its chunk) of the last 
  29. ; non-NULL tuple in the table. This can be 0 is last node is empty (entirely 
  30. ; NULL) or undefined if there are no chunks. FirstTupleOffset is unused.
  31.  
  32. TuplesPerChunk    equ    7    ; Ideally a power of 2 minus 1
  33.  
  34.     STRUCTURE    ScreenWindowTuple,0
  35.       APTR      Tuple_Screen
  36.       APTR      Tuple_Window
  37.     LABEL    Tuple_SIZEOF
  38.  
  39.     STRUCTURE    ScreenTableChunk,MLN_SIZE
  40.       STRUCT      Chunk_Data,Tuple_SIZEOF*TuplesPerChunk
  41.     LABEL    Chunk_SIZEOF
  42.  
  43.     STRUCTURE    ScreenTableType,MLH_SIZE
  44.       WORD      ST_FirstTupleOffset    ; \ Byte offset from chunk to
  45.       WORD      ST_LastTupleOffset    ; / start of first/last tuple
  46.     LABEL    ST_SIZEOF
  47.     
  48. ; PRIVATE routine to find the tuple associated with a particular screen if it
  49. ; can be found. Takes a0=^screen; Uses a5=^globals (for ScreenTable)
  50. ; Returns (d0=^chunk; d1=tup offset | d0=NULL; d1=?); Trashes nil.
  51. FindScreenTuple:
  52.     pushm.l    a1/d2
  53.     move.l    a0,d0    ;\ Return a NULL if
  54.     beq.s    .null    ;/ ^screen is NULL
  55.     move.l    ScreenTable+MLH_HEAD(a5),a1
  56. .loop      move.l      MLN_SUCC(a1),d0    ; d0 <- node after this one
  57.     beq.s    .null    ; fail if this is not really a node (the `next node' of the list header TAILPRED is NULL)
  58.       moveq      #Chunk_Data,d1    ; d1 <- offset of first tuple
  59.       moveq      #TuplesPerChunk-1,d2
  60. .dataloop        cmp.l        Tuple_Screen(a1,d1),a0
  61.     beq.s    .succeed    ; Exit early if we _do_ find the screen
  62.         addq.l        #Tuple_SIZEOF,d1    ; Get to next bit of data
  63.       dbra      d2,.dataloop
  64.       move.l      d0,a1    ; Get the next node
  65.     bra.s    .loop
  66. .succeed    move.l    a1,d0    ; d0 <- ^this chunk
  67. .null    popm.l    a1/d2    ; If we jump to here, d0 will equal NULL
  68.     rts
  69.  
  70. ; Routine to make screen table ready for use. Allocates all the necessary
  71. ; resources. Structure must initially be zeroed.
  72. ; Uses a5=^Globals (for ScreenTable); Trashes & Returns nil;
  73. InitialiseScreenTable:
  74.     ; << Shares code with ShutDownScreenTable >>
  75.  
  76. ; Routine to deallocate all of the screen table's resources and generally
  77. ; shut up shop. May be called even if structure is uninitialised (zeroed).
  78. ; Leaves screen table in an initialised state. (Deallocation is done 
  79. ; without keeping the list consistant betweentimes.)
  80. ; Uses a5=^Globals (for ScreenTable)
  81. ShutDownScreenTable:
  82.     pushm.l    a0-a2/d0-d2/a6
  83.     move.l    Execbase,a6
  84.     lea    ScreenTable+MLH_HEAD(a5),a2
  85.     move.l    (a2),d2
  86.     beq.s    .end    ; Quit early if not initialised
  87. .loop      move.l      d2,a1    ; thisnode <- nextnode
  88.       move.l      MLN_SUCC(a1),d2 ; nextnode <- thisnode.NEXT
  89.     beq.s    .end    ; Exit if no next node (in list header)
  90.       move.l      #Chunk_SIZEOF,d0
  91.       just      FreeMem    ; Free the memory of this node
  92.     bra.s    .loop    ; Keep looping 'til end of list
  93. .end    NEWLIST    a2    ; Make listheader self-consistant again
  94.     clr.l    ScreenTable+ST_FirstTupleOffset(a5)    ; Clears TWO words
  95.     popm.l    a0-a2/d0-d2/a6
  96.     rts
  97.  
  98. ; Routine to associate a particular window with a particular screen.
  99. ; Takes a0=^screen; a1=^window; Returns nil; Trashes nil.
  100. ; Uses a5=^globals (for ScreenTable and (locked) Intbase)
  101. ; Uses a2=^tuple; d1=last tuple offset; also a2,a3 = pointers to chunks 
  102. AssociateWindow:
  103.     cmp.w    #0,a0    ; \ First check that we have not been
  104.       beq.s      .return    ; / passed a NULL screen pointer
  105.     pushm.l    a2-a3/d0-d1
  106.     bsr    FindScreenTuple
  107.     move.l    d0,a2    ; a2 <- pointer to chunk
  108.     tst.l    d0
  109.     bne.s    .found    ; If FindScreenTuple(..) == NULL
  110.       move.l      ScreenTable+MLH_TAILPRED(a5),a2    ; Get last chunk
  111.       tst.l      MLN_PRED(a2)    ; Does it have a predecessor?
  112.       beq.s      .new_chunk    ; (If not, it isn't a proper node)
  113.         move.w        ScreenTable+ST_LastTupleOffset(a5),d1
  114.         addq.w        #Tuple_SIZEOF,d1    ; Compute new LastTuple offset
  115.         cmp.w        #Chunk_SIZEOF,d1
  116.       blo.s      .enoughroom    ; If last chunk is full up...
  117. .new_chunk        pushm.l        a0-a1/a6
  118.         move.l        Execbase,a6
  119.         move.l        #Chunk_SIZEOF,d0
  120.         move.l        #MEMF_CLEAR,d1
  121.         just        AllocMem    ; ...allocate a new one
  122.         popm.l        a0-a1/a6
  123.         tst.l        d0
  124.          beq.s         .end    ; (Can't allocate memory, so give up)
  125.         move.l        d0,MLN_SUCC(a2)
  126.         exg        d0,a2    ; d0 <- ^prev chunk; a2 <- ^new chunk
  127.         move.l        d0,MLN_PRED(a2)    
  128.         lea        ScreenTable+MLH_TAIL(a5),a3    ; a3 <- ^next chnk
  129.         move.l        a2,MLN_PRED(a3)
  130.         move.l        a3,MLN_SUCC(a2)
  131.         moveq        #Chunk_Data,d1
  132. .enoughroom      move.w      d1,ScreenTable+ST_LastTupleOffset(a5)
  133.       move.l      a0,Tuple_Screen(a2,d1.w)
  134. .found    move.l    a1,Tuple_Window(a2,d1.w)
  135. .end    popm.l    a2-a3/d0-d1
  136. .return    rts
  137.     
  138.  
  139. ; Routine to look up a screen in the table and return its associated window.
  140. ; Checks for existance of window. If window not in screen, returns frontmost
  141. ; window. WARNING: does not check for the existance of the screen (but does
  142. ; accept a NULL screen pointer, to which it returns NULL).
  143. ; Takes a0=^screen. Uses a5=^globals (uses ScreenTable and (locked) Intbase)
  144. ; Returns d0=^window. Trashes nil.
  145. IndexScreenTable:
  146.     pushm.l    a0-a1/d1
  147.     bsr    FindScreenTuple
  148.     tst.l    d0
  149.       beq.s      .end    ; Exit with d0=null if can't find screen
  150.     move.l    d0,a1
  151.     move.l    Tuple_Window(a1,d1.w),d0
  152.     move.l    sc_FirstWindow(a0),d1    ; Get first window in screen
  153. .windloop    beq.s    .closed    ; Return front window if no more windows
  154.       cmp.l      d1,d0    ; Is this the window we seek?
  155.     beq.s    .end    ; Found window in screen: success
  156.       move.l      d1,a1
  157.       move.l      wd_NextWindow(a1),d1    ; Else look at _next_ window
  158.     bra.s    .windloop    ; Keep looping 'til no more windows
  159. .end    popm.l    a0-a1/d1
  160.     rts
  161. .closed    move.l    sc_FirstWindow(a0),d0    ; Return the frontmost window
  162.     bra.s    .end    ; ...and exit
  163.  
  164. ; This routine garbage-collects non-existant (closed) screens from the table.
  165. ; Takes nil; Uses a5=^globals (for ScreenTable and (locked) Intbase)
  166. ; Returns nil; Trashes nil.
  167. ; Uses a0=^this chunk; d0=tuple offset; a1=^last chunk; d1=last tuple offset
  168. ; a2=^first screen; d2=^search screen; a3=^this screen; d3=tuple count
  169. ; a6=^execbase
  170. PruneScreenTable:
  171.     pushm.l    a0-a3/a6/d0-d3
  172.     move.w    ScreenTable+ST_LastTupleOffset(a5),d1
  173.     move.l    Execbase,a6
  174.     move.l    IntBase(a5),a2
  175.     move.l    ib_FirstScreen(a2),a2
  176.     lea    ScreenTable+MLH_HEAD(a5),a0
  177.     move.l    ScreenTable+MLH_TAILPRED(a5),a1    ; (It's okay: we check to see if the first node exists, and if _it_ exists, there must be a last node too.)
  178. .nextchunk      move.l      MLN_SUCC(a0),a0    ; Get next chunk after this
  179.       tst.l      MLN_SUCC(a0)    ; (Do it this way in case the successor node changes (is removed) while we have a cached next-node pointer, for example.)
  180.     beq.s    .endchunks    ; Exit if we are back to list header
  181.       moveq      #Chunk_Data,d0    ; Offset of actual data
  182.       moveq      #TuplesPerChunk-1,d3    ; Repeat TuplesPerChunk times
  183. .tupleloop        move.l        Tuple_Screen(a0,d0.w),d2    ; Get next tuple in chunk
  184.     beq.s    .endchunks ; NULL screen occurs only at end of list
  185.         lea        (a2),a3    ; Get the first screen on the system list
  186. .screenloop          cmp.l          a3,d2    ; Is this the screen we are looking for?
  187.         beq.s        .nexttuple    ; If found, on to next tuple
  188.           cmp.w          #0,a3    ; End of screen list?
  189.           movea.l     sc_NextScreen(a3),a3    ; (CCR unaffected)
  190.         bne.s        .screenloop    ; Stop looping at list end
  191.         bsr.s        .removescrn
  192. .nexttuple        addq.w        #Tuple_SIZEOF,d0    ; Offset of next datum
  193.       dbra      d3,.tupleloop    ; Loop on TuplesPerChunk
  194.     bra.s    .nextchunk    ; Loop on chunks
  195. .endchunks    move.w    d1,ScreenTable+ST_LastTupleOffset(a5)
  196.     popm.l    a0-a3/a6/d0-d3
  197.     rts
  198.  
  199.     ; Assume this bit is called only when:
  200.     ; a Tuple is to be removed; there are chunks in the list;
  201.     ; list is consistant and correct (very important);
  202.     ; a1=^last chunk; d1=LastTupOffset;
  203.     ; a0=^chunk; d0=offset (from a0) of any non-NULL tuple in list
  204.     ; If these rules are obeyed, we won't deallocate current node.
  205. .removescrn    tst.w    d1
  206.     bne.s    .dataleft    ; \ If LastTupleOffset==NULL, deallocate
  207.       pushm.l      a0/d0    ; / the last chunk
  208.       move.l      LN_SUCC(a1),a0    ; a0 <- tail of list
  209.       move.l      LN_PRED(a1),a3    ; a3 <- last chunk but one
  210.       move.l      a0,LN_SUCC(a3)
  211.       move.l      a3,LN_PRED(a0)
  212.       move.l      #Chunk_SIZEOF,d0
  213.       just      FreeMem
  214.       lea      (a3),a1    ; Now get the _new_ last chunk
  215.       move.l      #Chunk_SIZEOF-Tuple_SIZEOF,d1
  216.       popm.l      a0/d0
  217. .dataleft    move.l    Tuple_Screen(a1,d1.w),Tuple_Screen(a0,d0.w)
  218.     move.l    Tuple_Window(a1,d1.w),Tuple_Window(a0,d0.w)
  219.     clr.l    Tuple_Screen(a1,d1.w)    ;  | Replace this tuple with
  220.     clr.l    Tuple_Window(a1,d1.w)    ; /  the last one in the table
  221.     subq.w    #Tuple_SIZEOF,d1
  222.     rts
  223.  
  224.