mirror of
https://github.com/antoinevignau/source.git
synced 2024-11-19 22:31:52 +00:00
1 line
30 KiB
Plaintext
Executable File
1 line
30 KiB
Plaintext
Executable File
|
||
LOAD 'Macros.dump'
|
||
INCLUDE 'M16.Profile'
|
||
|
||
INCLUDE 'SS.equ'
|
||
|
||
INCLUDE 'Driver.equ'
|
||
INCLUDE 'Heap.aii.i'
|
||
INCLUDE 'Eval.aii.i'
|
||
|
||
;-----------------------------------------------
|
||
;
|
||
; Imported addresses
|
||
;
|
||
;-----------------------------------------------
|
||
|
||
IMPORT D_AlertBox
|
||
IMPORT D_BeachBall
|
||
IMPORT D_MainZPage
|
||
|
||
IMPORT S_CurChangedList
|
||
IMPORT S_CurDefFormat
|
||
IMPORT S_CurEditFlag
|
||
IMPORT S_DepOnMeTreeTooBig
|
||
IMPORT S_EvalFormula
|
||
IMPORT S_GetCellIndex
|
||
IMPORT S_GetCellPtr
|
||
IMPORT S_GetCellTableEntry
|
||
IMPORT S_GetRealCell
|
||
IMPORT S_IsCellCircular
|
||
IMPORT S_NewCell
|
||
IMPORT S_NormalizeRange
|
||
IMPORT S_RedrawCellRange
|
||
IMPORT S_RemoveCell
|
||
IMPORT S_SetCellIndex
|
||
IMPORT S_SetCellTableEntry
|
||
IMPORT S_TraverseRange
|
||
|
||
;-----------------------------------------------
|
||
;
|
||
; Forward addresses and entries
|
||
;
|
||
;-----------------------------------------------
|
||
|
||
ENTRY S_AddDepListToRecalc
|
||
ENTRY S_CalculateCell
|
||
ENTRY S_CheckForCirc
|
||
ENTRY S_FirstCallToCheckCircularity
|
||
ENTRY S_OrigCell
|
||
|
||
;-------------------------------------------------------------------------;
|
||
; S_AddCellToChangedList( Cell:l)
|
||
;
|
||
; S_AddCellToChangedList will add a cell to the changed list.
|
||
|
||
S_AddCellToChangedList PROC EXPORT
|
||
;Using S_CurrentData
|
||
|
||
input Cell:l
|
||
local CellPtr:l,DepListPtr:l,LastPtr:l
|
||
BEGIN
|
||
|
||
CellTableEntry equ CellPtr
|
||
|
||
in Cell:l
|
||
out CellTableEntry:l
|
||
XCall S_GetCellTableEntry
|
||
|
||
ora CellTableEntry
|
||
jeq Exit
|
||
|
||
lda CellTableEntry+2
|
||
and #S_CellTableFlags
|
||
beq realCell
|
||
|
||
; The cell to Mark changed, is not a real cell.
|
||
; We will Mark all cells in its DependOnMe list.
|
||
|
||
lda CellTableEntry+2
|
||
bpl fullList
|
||
|
||
and #$FFFF-S_CellTableFlags
|
||
tax
|
||
lda CellTableEntry
|
||
|
||
Call S_AddCellToChangedList,in=(ax:l)
|
||
brl Exit
|
||
|
||
fullList
|
||
and #$FFFF-S_CellTableFlags
|
||
sta CellTableEntry+2
|
||
|
||
H_GetBlockPtr CellTableEntry,DepListPtr
|
||
|
||
AddLong DepListPtr,[DepListPtr],LastPtr ; size
|
||
AddLong DepListPtr,#S_DependList,DepListPtr
|
||
|
||
loop
|
||
Call S_AddCellToChangedList,in=([DepListPtr]:l)
|
||
|
||
AddLong DepListPtr,#S_DependInc,DepListPtr
|
||
CmpLong DepListPtr,LastPtr
|
||
blt loop
|
||
|
||
brl Exit
|
||
|
||
realCell
|
||
H_GetBlockPtr CellTableEntry,CellPtr
|
||
|
||
MoveWord [CellPtr]:#S_CellNext,a ; chk if in list
|
||
ldy #S_CellNext+2
|
||
ora [CellPtr],y
|
||
bne Exit ; no long refs = 0
|
||
|
||
MoveLong #S_EndOfList,[CellPtr]:#S_CellPrevious
|
||
|
||
lda S_CurChangedList
|
||
ora S_CurChangedList+2
|
||
bne exists
|
||
|
||
MoveLong #S_EndOfList,[CellPtr]:#S_CellNext
|
||
bra fixCurChangedList
|
||
|
||
exists
|
||
MoveLong S_CurChangedList,[CellPtr]:#S_CellNext
|
||
|
||
in S_CurChangedList:l
|
||
out CellPtr:l
|
||
XCall S_GetCellPtr
|
||
|
||
MoveLong Cell,[CellPtr]:#S_CellPrevious
|
||
|
||
fixCurChangedList
|
||
MoveLong Cell,S_CurChangedList
|
||
|
||
Exit
|
||
RETURN
|
||
ENDP
|
||
|
||
;-------------------------------------------------------------------------;
|
||
; S_RemoveCellFromChangedList( Cell:l,NextCell:l )
|
||
;
|
||
; S_RemoveCellFromChangedList will remove a cell from the changed list.
|
||
; If the cell is not in the list, this routine will not work.
|
||
|
||
S_RemoveCellFromChangedList PROC EXPORT
|
||
;Using S_CurrentData
|
||
|
||
input Cell:l,PreviousCell:l,NextCell:l
|
||
local CellPtr:l
|
||
BEGIN
|
||
|
||
ProfileIn 3
|
||
|
||
CmpLong PreviousCell,#S_EndOfList
|
||
bne notHead
|
||
|
||
CmpLong NextCell,#S_EndOfList
|
||
beq clearList
|
||
|
||
MoveLong NextCell,S_CurChangedList
|
||
bra fixNext
|
||
|
||
clearList
|
||
stz S_CurChangedList
|
||
stz S_CurChangedList+2
|
||
bra Exit
|
||
|
||
notHead
|
||
in PreviousCell:l
|
||
out CellPtr:l
|
||
XCall S_GetCellPtr
|
||
|
||
MoveLong NextCell,[CellPtr]:#S_CellNext
|
||
|
||
|
||
; Before fixing the NextCell, make sure it is not the EndOfList.
|
||
|
||
CmpLong NextCell,#S_EndOfList
|
||
beq Exit
|
||
|
||
fixNext
|
||
in NextCell:l
|
||
out CellPtr:l
|
||
XCall S_GetCellPtr
|
||
|
||
MoveLong PreviousCell,[CellPtr]:#S_CellPrevious
|
||
|
||
Exit
|
||
|
||
ProfileOut 3
|
||
|
||
RETURN
|
||
ENDP
|
||
|
||
;-----------------------------------------------------------------------------
|
||
; S_RecalcList
|
||
;
|
||
|
||
S_NumOfRecalcBuckets equ 64
|
||
|
||
S_RecalcList DS.L S_NumOfRecalcBuckets
|
||
|
||
;-----------------------------------------------------------------------------
|
||
; S_ZeroRecalcList
|
||
;
|
||
|
||
S_ZeroRecalcList PROC EXPORT
|
||
|
||
BEGIN
|
||
|
||
ldx #S_NumOfRecalcBuckets<<2
|
||
lda #0
|
||
|
||
loop
|
||
dex
|
||
dex
|
||
sta S_RecalcList,x
|
||
bne loop
|
||
|
||
RETURN
|
||
ENDP
|
||
|
||
;-------------------------------------------------------------------------;
|
||
; S_AddCellToRecalcList( Cell:l )
|
||
;
|
||
; S_AddCellToRecalcList will add a cell to the recalculate list.
|
||
; The recalculate list is now implemented by a series of buckets.
|
||
; The buckets will contain those cells that need to be recalculated
|
||
; which have the lower n bits of the priority number equal to the
|
||
; bucket number.
|
||
|
||
|
||
S_AddCellToRecalcList PROC EXPORT
|
||
;Using S_CurrentData
|
||
|
||
input Cell:l
|
||
local RecalcPtr:l,CellPtr:l,CellPriority:w
|
||
local NextCell:l,NextPtr:l,BucketOffset:w
|
||
BEGIN
|
||
|
||
in Cell:l
|
||
out CellPtr:l
|
||
XCall S_GetCellPtr
|
||
|
||
ora CellPtr ; does this ever happen ?
|
||
beq toExit
|
||
|
||
MoveWord [CellPtr]:#S_CellFormat+2,a
|
||
and #S_CellCircular
|
||
bne toExit
|
||
|
||
MoveWord [CellPtr]:#S_CellNext,a ; checks if in a list
|
||
ldy #S_CellNext+2
|
||
ora [CellPtr],y
|
||
beq addToList ; no long refs = 0
|
||
|
||
toExit
|
||
brl Exit
|
||
|
||
; First figure out which bucket to add cell to and then do the
|
||
; insertion Sort on that bucket.
|
||
|
||
addToList
|
||
MoveWord [CellPtr]:#S_CellPriority,CellPriority
|
||
and #S_NumOfRecalcBuckets-1
|
||
asl a
|
||
asl a
|
||
sta BucketOffset
|
||
tax
|
||
|
||
lda S_RecalcList,x
|
||
ora S_RecalcList+2,x
|
||
bne exists
|
||
|
||
MoveLong Cell,S_RecalcList:x
|
||
MoveLong #S_EndOfList,[CellPtr]:#S_CellNext
|
||
|
||
brl Exit
|
||
|
||
exists
|
||
in S_RecalcList:x:l
|
||
out RecalcPtr:l
|
||
XCall S_GetCellPtr
|
||
|
||
CmpWord [RecalcPtr]:#S_CellPriority,CellPriority
|
||
blt startLoop
|
||
|
||
ldx BucketOffset
|
||
MoveLong S_RecalcList:x,[CellPtr]:#S_CellNext
|
||
MoveLong Cell,S_RecalcList:x
|
||
bra Exit
|
||
|
||
loop
|
||
MoveLong NextPtr,RecalcPtr
|
||
|
||
startLoop
|
||
MoveLong [RecalcPtr]:#S_CellNext,NextCell
|
||
|
||
CmpLong NextCell,#S_EndOfList
|
||
beq FoundPlace
|
||
|
||
in NextCell:l
|
||
out NextPtr:l
|
||
XCall S_GetCellPtr
|
||
|
||
CmpWord [NextPtr]:#S_CellPriority,CellPriority
|
||
blt loop
|
||
|
||
FoundPlace
|
||
MoveLong NextCell,[CellPtr]:#S_CellNext
|
||
MoveLong Cell,[RecalcPtr]:#S_CellNext
|
||
|
||
Exit
|
||
RETURN
|
||
ENDP
|
||
|
||
;-------------------------------------------------------------------------;
|
||
; S_AddCellToDepList( CellToEnter:l,TargetCell:l )
|
||
;
|
||
; S_AddCellToDepList will add a cell to another cell's dependency list.
|
||
|
||
S_AddCellToDepList PROC EXPORT
|
||
;Using S_CurrentData
|
||
|
||
input CellToEnter:l,TargetCell:l
|
||
local CellIndex:l,CellPtr:l,DependPtr:l
|
||
local DependSize:l,NewSize:l,DependList:l,LastPtr:l
|
||
local DependRangeList:l,NewRangeList:l,CellExists:w
|
||
local OtherCellInList:l
|
||
error ErrorFlag
|
||
BEGIN
|
||
|
||
stz ErrorFlag
|
||
stz CellExists
|
||
|
||
in TargetCell:l
|
||
out CellIndex:l
|
||
XCall S_GetCellTableEntry
|
||
|
||
ora CellIndex
|
||
beq noDepsOnMe
|
||
|
||
lda CellIndex+2
|
||
and #S_CellTableFlags
|
||
beq targetExists
|
||
|
||
MoveLong CellIndex,DependList
|
||
bra depListExists
|
||
|
||
; The TagetCell is real, so we have to dereference it to get the
|
||
; depend list if there is one.
|
||
|
||
targetExists
|
||
inc CellExists
|
||
|
||
H_GetBlockPtr CellIndex,CellPtr
|
||
|
||
MoveWord [CellPtr]:#S_CellDependOnMe,DependList
|
||
MoveWord [CellPtr]:#S_CellDependOnMe+2,DependList+2
|
||
|
||
ora DependList
|
||
bne depListExists
|
||
|
||
; There are no previous DependOnMe's for this TargetCell
|
||
; We will Create a short list (type: Single)
|
||
|
||
noDepsOnMe
|
||
MoveWord CellToEnter,DependList
|
||
|
||
lda CellToEnter+2
|
||
ora #S_CellTableSingDep
|
||
sta DependList+2
|
||
|
||
lda CellExists
|
||
jeq noCell
|
||
brl storeInCell
|
||
|
||
; Previous DependOnMe's exists, but we don't know how many and
|
||
; which type they are.
|
||
|
||
depListExists
|
||
lda DependList+2
|
||
jpl fullListExists
|
||
|
||
and #$FFFF-S_CellTableFlags
|
||
sta OtherCellInList+2
|
||
MoveWord DependList,OtherCellInList
|
||
|
||
lda DependList+2
|
||
and #S_CellTableFlags
|
||
cmp #S_CellTableRangeDep
|
||
beq singleAndRange
|
||
|
||
; The previous list was only one single dependency reference.
|
||
; Check to see if it is the CellToEnter, and if not, make a
|
||
; full dep list.
|
||
|
||
CmpLong CellToEnter,OtherCellInList
|
||
jeq Exit
|
||
|
||
MoveLong #S_DependStructSize+S_DependInc,DependRangeList
|
||
bra createList
|
||
|
||
; The previous list was only one range dependency reference.
|
||
; Make a full dep list.
|
||
|
||
singleAndRange
|
||
MoveLong #S_DependStructSize,DependRangeList
|
||
|
||
createList
|
||
H_NewBlock #S_DependStructSize+S_DependInc,DependList,DependPtr,err=ErrorFlag
|
||
jcs Exit
|
||
|
||
MoveLong #S_DependStructSize+S_DependInc,[DependPtr]:#S_DependSize
|
||
MoveLong DependRangeList,[DependPtr]:#S_DependRangeList
|
||
|
||
MoveLong CellToEnter,[DependPtr]:#S_DependList
|
||
MoveLong OtherCellInList,[DependPtr]:#S_DependList+S_DependInc
|
||
|
||
lda DependList+2
|
||
ora #S_CellTableList
|
||
sta DependList+2
|
||
|
||
; Determine where to store the New DependList just created.
|
||
|
||
lda CellExists
|
||
beq noCell
|
||
|
||
H_GetBlockPtr CellIndex,CellPtr
|
||
|
||
storeInCell
|
||
MoveLong DependList,[CellPtr]:#S_CellDependOnMe
|
||
brl Exit
|
||
|
||
noCell
|
||
in TargetCell:l,DependList:l
|
||
XCall S_SetCellTableEntry,err=ErrorFlag
|
||
brl Exit
|
||
|
||
|
||
; A previous full DependOnMe list exists, insert the New cell if it
|
||
; is not already in the list
|
||
|
||
fullListExists
|
||
; lda DependList+2 ; already in 'a'
|
||
and #-1-S_CellTableList
|
||
sta DependList+2
|
||
|
||
; Search the original list.
|
||
|
||
H_GetBlockPtr DependList,DependPtr
|
||
|
||
MoveLong [DependPtr]:#S_DependSize,DependSize
|
||
MoveLong [DependPtr]:#S_DependRangeList,DependRangeList
|
||
|
||
AddLong DependPtr,DependRangeList,LastPtr
|
||
AddLong DependPtr,#S_DependList,DependPtr
|
||
bra cmpPtrs
|
||
|
||
SearchLoop
|
||
CmpLong [DependPtr],CelltoEnter
|
||
jeq Exit
|
||
|
||
AddLong DependPtr,#S_DependInc,DependPtr
|
||
|
||
cmpPtrs
|
||
CmpLong DependPtr,LastPtr
|
||
blt SearchLoop
|
||
|
||
; Cell is not already in DependOnMe List ;
|
||
|
||
AddLong DependSize,#S_DependInc,NewSize
|
||
AddLong DependRangeList,#S_DependInc,NewRangeList
|
||
|
||
H_ResizeBlock DependList,NewSize,DependPtr,err=ErrorFlag
|
||
bcs Exit
|
||
|
||
AddLong DependPtr,DependRangeList,s
|
||
AddLong DependPtr,NewRangeList,s
|
||
SubLong DependSize,DependRangeList,s
|
||
Tool _BlockMove
|
||
|
||
MoveLong NewSize,[DependPtr]:#S_DependSize
|
||
MoveLong NewRangeList,[DependPtr]:#S_DependRangeList
|
||
|
||
AddLong DependRangeList,DependPtr,DependPtr
|
||
MoveLong CellToEnter,[DependPtr]
|
||
|
||
Exit
|
||
RETURN
|
||
ENDP
|
||
|
||
;-------------------------------------------------------------------------;
|
||
; S_RemoveCellFromDepList( CellToRemove:l,TargetCell:l )
|
||
;
|
||
; S_RemoveCellFromDepList will remove a cell from another cell's dependency
|
||
; list.
|
||
|
||
S_RemoveCellFromDepList PROC EXPORT
|
||
;Using S_CurrentData
|
||
|
||
input CellToRemove:l,TargetCell:l
|
||
local CellIndex:l
|
||
local CellPtr:l,DependList:l,DependPtr:l,NewDependList:l
|
||
local DependSize:l,NewSize:l,NextPtr:l,LastPtr:l
|
||
local DependRangeList:l,NewRangeList:l,CellExists:w
|
||
error ErrorFlag
|
||
BEGIN
|
||
|
||
stz ErrorFlag
|
||
stz CellExists
|
||
|
||
in TargetCell:l
|
||
out CellIndex:l
|
||
XCall S_GetCellTableEntry
|
||
|
||
ora CellIndex
|
||
beq toExit
|
||
|
||
lda CellIndex+2
|
||
and #S_CellTableFlags
|
||
beq targetExists
|
||
|
||
MoveLong CellIndex,DependList
|
||
bra depListExists
|
||
|
||
; The TargetCell is real, so we have to de-reference it to get the
|
||
; DependOnMe list, if there is one.
|
||
|
||
targetExists
|
||
inc CellExists
|
||
|
||
H_GetBlockPtr CellIndex,CellPtr
|
||
|
||
MoveWord [CellPtr]:#S_CellDependOnMe,DependList
|
||
MoveWord [CellPtr]:#S_CellDependOnMe+2,DependList+2
|
||
|
||
ora DependList
|
||
bne depListExists
|
||
|
||
toExit
|
||
brl Exit
|
||
|
||
; Previous DependOnMe's exist, but we don't know how many and of
|
||
; of which type they are.
|
||
|
||
depListExists
|
||
lda DependList+2
|
||
bpl fullListExists
|
||
|
||
; Only one previous DependOnMe.
|
||
|
||
and #S_CellTableFlags
|
||
cmp #S_CellTableRangeDep
|
||
beq toExit
|
||
|
||
; It was a single reference, chk to see if it is the CellToRemove
|
||
|
||
lda DependList+2
|
||
and #$FFFF-S_CellTableFlags
|
||
cmp CellToRemove+2
|
||
bne toExit
|
||
|
||
CmpWord DependList,CellToRemove
|
||
bne toExit
|
||
|
||
; It was, replace it with no list.
|
||
|
||
stzl NewDependList
|
||
brl storeDepList
|
||
|
||
; A previous full DependOnMe list exists, chk the following.
|
||
; 1) Are there any single references.
|
||
; 2) Is there more than two references.
|
||
; 3) Is there two single references, or one single and one range reference.
|
||
|
||
fullListExists
|
||
lda DependList+2
|
||
and #-1-S_CellTableList
|
||
sta DependList+2
|
||
|
||
H_GetBlockPtr DependList,DependPtr
|
||
|
||
CmpLong [DependPtr]:#S_DependRangeList,#S_DependList
|
||
jeq Exit
|
||
|
||
CmpLong #S_DependStructSize+S_DependInc,[DependPtr]:#S_DependSize
|
||
jne moreThanTwo
|
||
|
||
CmpLong [DependPtr]:#S_DependRangeList,#S_DependList+S_DependInc
|
||
bne twoSingles
|
||
|
||
; There is one single and one range reference, if the single reference
|
||
; is the CellToRemove, then leave a short list (type: range)
|
||
|
||
CmpLong CellToRemove,[DependPtr]:#S_DependList
|
||
jne Exit
|
||
|
||
MoveWord [DependPtr]:#S_DependList+S_DependInc,NewDependList
|
||
|
||
MoveWord [DependPtr]:#S_DependList+S_DependInc+2,a
|
||
ora #S_CellTableRangeDep
|
||
sta NewDependList+2
|
||
|
||
bra killDepList
|
||
|
||
; There are two single references. Check if either one is the CellToRemove.
|
||
; If so, leave the other in a short list. (type: single)
|
||
|
||
twoSingles
|
||
CmpLong CellToRemove,[DependPtr]:#S_DependList
|
||
bne notFirst
|
||
|
||
MoveWord [DependPtr]:#S_DependList+S_DependInc,NewDependList
|
||
MoveWord [DependPtr]:#S_DependList+S_DependInc+2,a
|
||
|
||
bra setSingle
|
||
|
||
notFirst
|
||
CmpLong CellToRemove,[DependPtr]:#S_DependList+S_DependInc
|
||
jne Exit
|
||
|
||
MoveWord [DependPtr]:#S_DependList,NewDependList
|
||
MoveWord [DependPtr]:#S_DependList+2,a
|
||
|
||
setSingle
|
||
ora #S_CellTableSingDep
|
||
sta NewDependList+2
|
||
|
||
killDepList
|
||
H_DisposeBlock DependList
|
||
|
||
; Determine where to store the NewDependList
|
||
|
||
storeDepList
|
||
lda CellExists
|
||
beq noCell
|
||
|
||
MoveLong NewDependList,[CellPtr]:#S_CellDependOnMe
|
||
brl Exit
|
||
|
||
noCell
|
||
Call S_SetCellTableEntry,in=(TargetCell:l,NewDependList:l)
|
||
brl Exit
|
||
|
||
; There are more than two DependOnMe references. Check if the CellToRemove
|
||
; is in the single list, and remove it.
|
||
|
||
moreThanTwo
|
||
MoveLong [DependPtr]:#S_DependSize,DependSize
|
||
MoveLong [DependPtr]:#S_DependRangeList,DependRangeList
|
||
|
||
AddLong DependPtr,DependRangeList,LastPtr
|
||
AddLong DependPtr,#S_DependList,NextPtr
|
||
|
||
SearchLoop
|
||
CmpLong [NextPtr],CelltoRemove
|
||
beq found
|
||
|
||
AddLong NextPtr,#S_DependInc,NextPtr
|
||
CmpLong NextPtr,LastPtr
|
||
blt SearchLoop
|
||
brl Exit
|
||
|
||
found
|
||
SubLong DependSize,#S_DependInc,NewSize
|
||
SubLong DependRangeList,#S_DependInc,NewRangeList
|
||
|
||
MoveLong NewSize,[DependPtr]:#S_DependSize
|
||
MoveLong NewRangeList,[DependPtr]:#S_DependRangeList
|
||
|
||
AddLong NextPtr,#S_DependInc,s
|
||
PushLong NextPtr
|
||
AddLong DependPtr,DependSize,s
|
||
SubLong 1:s,NextPtr,1:s
|
||
Tool _BlockMove
|
||
|
||
H_ResizeBlock DependList,NewSize ; resize smaller always works
|
||
|
||
Exit
|
||
RETURN
|
||
ENDP
|
||
|
||
;-------------------------------------------------------------------------;
|
||
; S_CalculateSheet
|
||
;
|
||
; S_CalculateSheet will handle the calculation of all necessary cells.
|
||
|
||
S_CalculateSheet PROC EXPORT
|
||
;Using S_CurrentData
|
||
|
||
local RecalcIndex:l,RecalcPtr:l
|
||
local Cell:l,CellPtr:l,Next:l,HighFormat:w
|
||
local CurrentPriority:w,CurrentBucket:w,LastBucket:w
|
||
local LowestPriority:w,BestBucket:w
|
||
error ErrFlag
|
||
BEGIN
|
||
|
||
stz ErrFlag
|
||
|
||
lda S_CurChangedList
|
||
ora S_CurChangedList+2
|
||
jeq Exit
|
||
|
||
; Put the changed list in the recalc list. The recalc list is now
|
||
; a series of buckets, so that the sorting process will go much
|
||
; faster on long lists.
|
||
|
||
Call S_ZeroRecalcList
|
||
|
||
MoveLong S_CurChangedList,Next
|
||
|
||
changedLoop
|
||
Call D_BeachBall
|
||
|
||
MoveLong Next,Cell
|
||
|
||
in Cell:l
|
||
out CellPtr:l
|
||
XCall S_GetCellPtr
|
||
|
||
MoveLong [CellPtr]:#S_CellNext,Next
|
||
|
||
lda #0
|
||
MoveWord a,[CellPtr]:#S_CellNext
|
||
MoveWord a,[CellPtr]:#S_CellNext+2
|
||
MoveWord a,[CellPtr]:#S_CellPrevious
|
||
MoveWord a,[CellPtr]:#S_CellPrevious+2
|
||
|
||
MoveWord [CellPtr]:#S_CellFormat,a
|
||
bmi addDepList ; branch pad cells
|
||
|
||
and #S_CellTypeTextForm
|
||
bne addToRecalc ; branch all formulas
|
||
|
||
addDepList
|
||
Call S_AddDepListToRecalc,in=(Cell:l)
|
||
bra getNextCell
|
||
|
||
addToRecalc
|
||
Call S_AddCellToRecalcList,in=(Cell:l)
|
||
|
||
getNextCell
|
||
CmpLong Next,#S_EndOfList
|
||
bne changedLoop
|
||
|
||
|
||
stz S_CurChangedList
|
||
stz S_CurChangedList+2
|
||
|
||
; Start re-calculating ;
|
||
|
||
; Things to remember: 1) The RecalcList must be maintained
|
||
; during calculation, so that New
|
||
; cells may be added to it.
|
||
|
||
stz CurrentPriority
|
||
stz CurrentBucket
|
||
|
||
startFindNext
|
||
ldx CurrentBucket
|
||
|
||
SubWord x,#4,a
|
||
and #(S_NumOfRecalcBuckets<<2)-1
|
||
sta LastBucket
|
||
|
||
MoveWord #-1,LowestPriority
|
||
|
||
loopN
|
||
lda S_RecalcList,x
|
||
ora S_RecalcList+2,x
|
||
beq contSearch
|
||
|
||
; There is a list here, check if the first cell is of the
|
||
; right priority, if not, remember the lowest priority and
|
||
; continue the search.
|
||
|
||
stx CurrentBucket
|
||
|
||
in S_RecalcList:x:l
|
||
out CellPtr:l
|
||
XCall S_GetCellPtr
|
||
|
||
CmpWord [CellPtr]:#S_CellPriority,CurrentPriority
|
||
beq doThisCell
|
||
|
||
ldx CurrentBucket
|
||
|
||
CmpWord [CellPtr]:y,LowestPriority
|
||
bge contSearch
|
||
|
||
sta LowestPriority
|
||
stx BestBucket
|
||
|
||
contSearch
|
||
cpx LastBucket
|
||
beq lookedAtAll
|
||
|
||
inc CurrentPriority
|
||
|
||
AddWord x,#4,a
|
||
and #(S_NumOfRecalcBuckets<<2)-1
|
||
tax
|
||
bra loopN
|
||
|
||
; We've looked at all of the buckets, and didn't find any
|
||
; of the right priority, on this pass. If we saw any cells,
|
||
; we have remembered the lowest priority.
|
||
|
||
lookedAtAll
|
||
CmpWord LowestPriority,#-1
|
||
jeq Exit
|
||
|
||
MoveWord BestBucket,CurrentBucket
|
||
tax
|
||
|
||
in S_RecalcList:x:l
|
||
out CellPtr:l
|
||
XCall S_GetCellPtr
|
||
|
||
MoveWord [CellPtr]:#S_CellPriority,CurrentPriority
|
||
|
||
; This is the next cell to recalculate. We'll first fix up the
|
||
; list it is in, calculate it, and then add it's dependencies.
|
||
; Then we start the search loop over to find the next cell to
|
||
; calculate.
|
||
|
||
doThisCell
|
||
ldx CurrentBucket
|
||
MoveLong S_RecalcList:x,Cell
|
||
MoveLong [CellPtr]:#S_CellNext,S_RecalcList:x
|
||
|
||
CmpLong S_RecalcList:x,#S_EndOfList
|
||
bne recalcSet
|
||
|
||
MoveWord #0,S_RecalcList:x
|
||
sta S_RecalcList+2,x
|
||
|
||
recalcSet
|
||
MoveLong #0,[CellPtr]:#S_CellNext
|
||
|
||
Call S_CalculateCell,in=(Cell:l),err=ErrFlag
|
||
bcs calcMemError
|
||
|
||
Call S_AddDepListToRecalc,in=(Cell:l)
|
||
|
||
lda S_CurEditFlag
|
||
and #S_ViewFormulaBit
|
||
bne getNextCell2
|
||
|
||
Call S_RedrawCellRange,in=(Cell:l,Cell:l)
|
||
|
||
getNextCell2
|
||
brl startFindNext
|
||
|
||
; We had a memory error during recalculation. This can happen
|
||
; when the result of a formula is a string, and there isn't
|
||
; enough memory in the heap to hold the string.
|
||
|
||
; We need to remember all the cells that need to be recalculated
|
||
; and recalculate them the next time S_CalculateSheet is called.
|
||
|
||
calcMemError
|
||
Call S_AddCellToRecalcList,in=(Cell:l)
|
||
stz CurrentBucket
|
||
|
||
errorLoop
|
||
ldx CurrentBucket
|
||
|
||
lda S_RecalcList,x
|
||
ora S_RecalcList+2,x
|
||
beq noneHere
|
||
|
||
MoveLong S_RecalcList:x,Cell
|
||
|
||
in Cell:l
|
||
out CellPtr:l
|
||
XCall S_GetCellPtr
|
||
|
||
ldx CurrentBucket
|
||
MoveLong [CellPtr]:#S_CellNext,S_RecalcList:x
|
||
MoveLong #0,[CellPtr]:#S_CellNext
|
||
|
||
CmpLong Cell,#S_EndOfList
|
||
bne addToCanged
|
||
|
||
MoveWord #0,S_RecalcList:x
|
||
sta S_RecalcList+2,x
|
||
|
||
addToCanged
|
||
Call S_AddCellToChangedList,in=(Cell:l)
|
||
bra errorLoop
|
||
|
||
noneHere
|
||
AddWord CurrentBucket,#4,a
|
||
and #(S_NumOfRecalcBuckets<<2)-1
|
||
sta CurrentBucket
|
||
bne errorLoop
|
||
|
||
Exit
|
||
RETURN
|
||
ENDP
|
||
|
||
;-------------------------------------------------------------------------;
|
||
; S_AddDepListToRecalc( Cell:l )
|
||
;
|
||
; S_AddListToRecalc will add a cell's dependency list to the recalculate
|
||
; list.
|
||
|
||
S_AddDepListToRecalc PROC EXPORT
|
||
;Using S_CurrentData
|
||
|
||
input Cell:l
|
||
local CellPtr:l,DepListPtr:l
|
||
local LastPtr:l,DependList:l
|
||
BEGIN
|
||
|
||
in Cell:l
|
||
out CellPtr:l
|
||
XCall S_GetCellPtr
|
||
|
||
ora CellPtr
|
||
jeq Exit
|
||
|
||
MoveWord [CellPtr]:#S_CellDependOnMe,DependList
|
||
MoveWord [CellPtr]:#S_CellDependOnMe+2,DependList+2
|
||
|
||
ora DependList
|
||
beq Exit
|
||
|
||
lda DependList+2
|
||
bpl fullList
|
||
|
||
and #$FFFF-S_CellTableFlags
|
||
pha
|
||
PushWord DependList
|
||
Call S_AddCellToRecalcList,in=(:l)
|
||
bra Exit
|
||
|
||
fullList
|
||
and #$FFFF-S_CellTableFlags
|
||
sta DependList+2
|
||
|
||
H_GetBlockPtr DependList,DepListPtr
|
||
|
||
AddLong DepListPtr,[DepListPtr],LastPtr ; size
|
||
AddLong DepListPtr,#S_DependList,DepListPtr
|
||
|
||
loop
|
||
Call S_AddCellToRecalcList,in=([DepListPtr]:l)
|
||
|
||
AddLong DepListPtr,#S_DependInc,DepListPtr
|
||
CmpLong DepListPtr,LastPtr
|
||
blt loop
|
||
|
||
Exit
|
||
RETURN
|
||
ENDP
|
||
|
||
;-------------------------------------------------------------------------;
|
||
; S_CalculateCell( Cell:l )
|
||
;
|
||
; S_CalculateCell will handle the calculation of an individual cell.
|
||
|
||
S_CalculateCell PROC EXPORT
|
||
;Using S_CurrentData
|
||
|
||
input Cell:l
|
||
local CellIndex:l
|
||
local CellPtr:l,RefCellPtr:l,ContentPtr:l
|
||
error ErrFlag
|
||
BEGIN
|
||
|
||
stz ErrFlag
|
||
|
||
Call D_BeachBall
|
||
|
||
in Cell:l
|
||
out CellIndex:l
|
||
XCall S_GetCellIndex
|
||
|
||
H_GetBlockPtr CellIndex,CellPtr
|
||
|
||
MoveWord [CellPtr]:#S_CellFormat,a
|
||
bmi Exit
|
||
|
||
and #S_CellTypeTextForm ; checks formula bit
|
||
beq Exit
|
||
|
||
MoveWord [CellPtr]:#S_CellFormat+2,a
|
||
and #S_CellCircular
|
||
bne Exit
|
||
|
||
Call S_EvalFormula,in=(CellIndex:l),err=ErrFlag
|
||
|
||
Exit
|
||
RETURN
|
||
ENDP
|
||
|
||
;----------------------------------------------------------------------------
|
||
; S_CheckStack
|
||
;
|
||
|
||
S_CheckStack PROC EXPORT
|
||
|
||
tsc
|
||
pha
|
||
AddWord >D_MainZPage,#1024,a
|
||
cmp 1,s ; carry set = limit <20> stack
|
||
pla
|
||
rtl
|
||
|
||
;----------------------------------------------------------------------------
|
||
; S_TraverseDependOnMeTree
|
||
;
|
||
; This routine will start at the given cell and call a given routine on that
|
||
; cell and all cells in the dependency branch until/unless an abort signal is
|
||
; passed back from the traverse routine. The traverse routine should be of
|
||
; the following form:
|
||
;
|
||
; S_TraverseRoutine,in=(CellPtr:l),out=(ProceedCode:w),err=AbortTraverse
|
||
;
|
||
|
||
S_TraverseDependOnMeTree PROC EXPORT
|
||
;Using S_CurrentData
|
||
;Using S_PriorityData
|
||
|
||
input Cell:l,Routine:l
|
||
local CellPtr:l,DependList:l,DepListPtr:l,LastPtr:l
|
||
local OrigStack:w,NoRoomMsg:w,OverflowIndex:w,OverflowArray:l
|
||
error AbortTraverse
|
||
BEGIN
|
||
|
||
stz AbortTraverse
|
||
stz NoRoomMsg
|
||
stz OverflowIndex
|
||
stz OverflowArray+2
|
||
AddWord >D_MainZPage,#256,OverflowArray
|
||
|
||
tsc
|
||
sta OrigStack
|
||
|
||
MoveWord Routine,>Slot+1
|
||
MoveWord Routine+1,>Slot+2
|
||
|
||
startRoutine
|
||
lda #0
|
||
pha
|
||
pha
|
||
pha
|
||
pha
|
||
|
||
beginCell
|
||
Call S_CheckStack
|
||
bcc stackOK
|
||
|
||
jsr handleOverFlow
|
||
brl endCell
|
||
|
||
stackOK
|
||
in Cell:l
|
||
out CellPtr:l
|
||
XCall S_GetCellPtr
|
||
|
||
ora CellPtr
|
||
jeq endCell
|
||
|
||
; Make Call
|
||
|
||
SpaceWord
|
||
PushLong CellPtr
|
||
slot Call >0
|
||
sta AbortTraverse
|
||
PullWord
|
||
jcs cleanStack
|
||
|
||
; The result of the routine will tell if this branch of the tree
|
||
; should be traversed or skipped.
|
||
|
||
jne endCell
|
||
|
||
; Now loop on the DependOnMe list and make an iteration for each of the
|
||
; the cells that depend on this cell.
|
||
|
||
MoveWord [CellPtr]:#S_CellDependOnMe,DependList
|
||
MoveWord [CellPtr]:#S_CellDependOnMe+2,DependList+2
|
||
|
||
ora DependList
|
||
beq endCell
|
||
|
||
lda DependList+2
|
||
bpl doFullList
|
||
|
||
and #$FFFF-S_CellTableFlags
|
||
sta DependList+2
|
||
|
||
MoveLong !DependList,DepListPtr
|
||
stzl LastPtr
|
||
bra dependLoop
|
||
|
||
doFullList
|
||
and #$FFFF-S_CellTableFlags
|
||
tay
|
||
ldx DependList
|
||
H_GetBlockPtr xy,DepListPtr
|
||
|
||
AddLong DepListPtr,[DepListPtr],LastPtr
|
||
AddLong DepListPtr,#S_DependList,DepListPtr
|
||
|
||
; We want this routine to be iterative, not recursive, so as to use less
|
||
; stack space.
|
||
|
||
dependLoop
|
||
PushLong DepListPtr
|
||
PushLong LastPtr
|
||
MoveLong [DepListPtr],Cell
|
||
brl beginCell
|
||
|
||
endCell
|
||
PullLong LastPtr
|
||
PullWord DepListPtr
|
||
PullWord DepListPtr+2
|
||
|
||
ora DepListPtr
|
||
beq recoverOverflow
|
||
|
||
AddLong DepListPtr,#S_DependInc,DepListPtr
|
||
CmpLong DepListPtr,LastPtr
|
||
blt dependLoop
|
||
bra endCell
|
||
|
||
recoverOverflow
|
||
lda OverflowIndex
|
||
beq chkMsg
|
||
|
||
SubWord OverflowIndex,#4,OverflowIndex
|
||
MoveLong [OverflowArray]:OverflowIndex,Cell
|
||
brl startRoutine
|
||
|
||
; We jump to here if we want to abort the traversal. We need to
|
||
; clean up the stack.
|
||
|
||
cleanStack
|
||
lda OrigStack
|
||
tcs
|
||
|
||
chkMsg
|
||
lda NoRoomMsg
|
||
beq Exit
|
||
|
||
Call D_AlertBox,in=(#OKBox:w,#S_DepOnMeTreeTooBig:l),out=(a:w)
|
||
|
||
Exit
|
||
RETURN
|
||
|
||
handleOverFlow
|
||
ldy OverflowIndex
|
||
cpy #260
|
||
bge noRoom
|
||
|
||
MoveLong Cell,[OverflowArray]:y
|
||
AddWord OverflowIndex,#4,OverflowIndex
|
||
rts
|
||
|
||
noRoom
|
||
MoveWord #1,NoRoomMsg
|
||
rts
|
||
|
||
ENDP
|
||
|
||
;-------------------------------------------------------------------------;
|
||
; S_CheckCellCircularity
|
||
;
|
||
;
|
||
|
||
S_CheckCellCircularity PROC EXPORT
|
||
|
||
EXPORT S_FirstCallToCheckCircularity
|
||
EXPORT S_OrigCell
|
||
|
||
input CellPtr:l
|
||
output ProceedCode:w
|
||
error AbortFlag
|
||
BEGIN
|
||
|
||
stz AbortFlag
|
||
|
||
lda S_FirstCallToCheckCircularity
|
||
bne firstCall
|
||
|
||
CmpLong [CellPtr]:#S_CellId,S_OrigCell
|
||
bne noCircularity
|
||
|
||
MoveWord #-1,AbortFlag
|
||
brl exit
|
||
|
||
firstCall
|
||
stz S_FirstCallToCheckCircularity
|
||
|
||
noCircularity
|
||
ldy #S_CellFormat+2
|
||
lda [CellPtr],y
|
||
and #S_CellCircular+S_CellVisited
|
||
bne deadEnd
|
||
|
||
lda [CellPtr],y
|
||
ora #S_CellVisited
|
||
sta [CellPtr],y
|
||
|
||
stz ProceedCode
|
||
bra exit
|
||
|
||
deadEnd
|
||
MoveWord #1,ProceedCode
|
||
|
||
exit
|
||
RETURN
|
||
|
||
S_FirstCallToCheckCircularity
|
||
DS.W 1
|
||
S_OrigCell DS.L 1
|
||
|
||
ENDP
|
||
|
||
;-------------------------------------------------------------------------;
|
||
; S_SetCellCircular
|
||
;
|
||
;
|
||
|
||
S_SetCellCircular PROC EXPORT
|
||
|
||
input CellPtr:l
|
||
output ProceedCode:w
|
||
error AbortFlag
|
||
BEGIN
|
||
|
||
stz AbortFlag
|
||
|
||
ldy #S_CellFormat+2
|
||
lda [CellPtr],y
|
||
and #S_CellCircular
|
||
beq setIt
|
||
|
||
MoveWord #1,ProceedCode
|
||
bra exit
|
||
|
||
setIt
|
||
lda [CellPtr],y
|
||
and #-1-S_CellVisited
|
||
ora #S_CellCircular
|
||
sta [CellPtr],y
|
||
|
||
; Clear the value of this cell ;
|
||
|
||
ldy #S_CellFormat
|
||
lda [CellPtr],y
|
||
and #S_CellType
|
||
cmp #S_CellTypeTextForm
|
||
bne storeZero
|
||
|
||
lda [CellPtr],y
|
||
and #$FFFF-S_CellType
|
||
ora #S_CellTypeFormula
|
||
sta [CellPtr],y
|
||
|
||
H_DisposeBlock [CellPtr]:#S_CellValue
|
||
|
||
storeZero
|
||
lda #0
|
||
ldy #S_CellValue
|
||
ldx #5
|
||
|
||
zeroLoop
|
||
sta [CellPtr],y
|
||
iny
|
||
iny
|
||
dex
|
||
bne zeroLoop
|
||
|
||
; Draw the circ. cell ;
|
||
|
||
MoveWord [CellPtr]:#S_CellId+2,a
|
||
tax
|
||
MoveWord [CellPtr]:#S_CellId,a
|
||
Call S_RedrawCellRange,in=(ax:l,ax:l)
|
||
|
||
stz ProceedCode
|
||
|
||
exit
|
||
RETURN
|
||
ENDP
|
||
|
||
;-------------------------------------------------------------------------;
|
||
; S_ClearCellVisited
|
||
;
|
||
; The whole DependOnMe tree had visited bits set, before this routine
|
||
; started to clear them.
|
||
|
||
S_ClearCellVisited PROC EXPORT
|
||
|
||
input CellPtr:l
|
||
output ProceedCode:w
|
||
error AbortFlag
|
||
BEGIN
|
||
|
||
stz AbortFlag
|
||
|
||
; If the visited bit is not set, then we have already cleared it,
|
||
; and all of the cells past this point in the DependOnMe tree have
|
||
; also been cleared.
|
||
|
||
ldy #S_CellFormat+2
|
||
lda [CellPtr],y
|
||
and #S_CellVisited
|
||
beq deadEnd
|
||
|
||
; Clear the bit.
|
||
|
||
lda [CellPtr],y
|
||
and #-1-S_CellVisited
|
||
sta [CellPtr],y
|
||
|
||
stz ProceedCode
|
||
bra exit
|
||
|
||
deadEnd
|
||
MoveWord #1,ProceedCode
|
||
|
||
exit
|
||
RETURN
|
||
ENDP
|
||
|
||
;-------------------------------------------------------------------------;
|
||
; S_SetCircularBits
|
||
;
|
||
;
|
||
|
||
S_SetCircularBits PROC EXPORT
|
||
;Using S_CurrentData
|
||
|
||
input Cell:l
|
||
local CellPtr:l
|
||
BEGIN
|
||
|
||
in Cell:l
|
||
out CellPtr:l
|
||
XCall S_GetCellPtr
|
||
|
||
ora CellPtr
|
||
beq Exit
|
||
|
||
; Check if any of the cells in the formula are circular.
|
||
; If so, set all cells depending on this routine as circular.
|
||
|
||
in Cell:l,[CellPtr]:#S_CellContent:l
|
||
out a:w
|
||
XCall S_CheckForCirc
|
||
bne setCircularity
|
||
|
||
|
||
; Traverse DependOnMe checking for circularity ;
|
||
|
||
MoveWord #-1,S_FirstCallToCheckCircularity
|
||
MoveLong Cell,S_OrigCell
|
||
|
||
in Cell:l,#S_CheckCellCircularity:l
|
||
XCall S_TraverseDependOnMeTree
|
||
bcc clearVisited
|
||
|
||
|
||
; Traverse DependOnMe setting the circularity bits ;
|
||
|
||
setCircularity
|
||
in Cell:l,#S_SetCellCircular:l
|
||
XCall S_TraverseDependOnMeTree
|
||
bra Exit
|
||
|
||
|
||
; Traverse DependOnMe clearing the visited bits ;
|
||
|
||
clearVisited
|
||
in Cell:l,#S_ClearCellVisited:l
|
||
XCall S_TraverseDependOnMeTree
|
||
|
||
Exit
|
||
RETURN
|
||
ENDP
|
||
|
||
;-------------------------------------------------------------------------;
|
||
; S_ClearCellCircular
|
||
;
|
||
; The whole DependOnMe tree had visited bits set, before this routine
|
||
; started to clear them.
|
||
|
||
S_ClearCellCircular PROC EXPORT
|
||
|
||
input CellPtr:l
|
||
output ProceedCode:w
|
||
error AbortFlag
|
||
BEGIN
|
||
|
||
stz AbortFlag
|
||
|
||
; If the visited bit is not set, then we have already cleared it,
|
||
; and all of the cells past this point in the DependOnMe tree have
|
||
; also been cleared.
|
||
|
||
ldy #S_CellFormat+2
|
||
lda [CellPtr],y
|
||
and #S_CellCircular
|
||
beq deadEnd
|
||
|
||
; Should the bit be cleared?
|
||
|
||
in [CellPtr]:#S_CellId:l,[CellPtr]:#S_CellContent:l
|
||
out a:w
|
||
XCall S_CheckForCirc
|
||
bne deadEnd
|
||
|
||
; Clear the bit.
|
||
|
||
ldy #S_CellFormat+2
|
||
lda [CellPtr],y
|
||
and #-1-S_CellCircular
|
||
sta [CellPtr],y
|
||
|
||
stz ProceedCode
|
||
bra exit
|
||
|
||
deadEnd
|
||
MoveWord #1,ProceedCode
|
||
|
||
exit
|
||
RETURN
|
||
ENDP
|
||
|
||
;-------------------------------------------------------------------------;
|
||
; S_ResetCircularBits
|
||
;
|
||
;
|
||
|
||
S_ResetCircularBits PROC EXPORT
|
||
;Using S_CurrentData
|
||
|
||
input Cell:l
|
||
BEGIN
|
||
|
||
in Cell:l,#S_ClearCellCircular:l
|
||
XCall S_TraverseDependOnMeTree
|
||
|
||
RETURN
|
||
ENDP
|
||
|
||
;-----------------------------------------------------------------------------
|
||
; S_CheckForCirc( Cell:l, ContentIndex:l ) , CircFlag:w
|
||
;
|
||
|
||
S_CheckForCirc PROC EXPORT
|
||
;Using S_CurrentData
|
||
|
||
input Cell:l,ContentIndex:l
|
||
output CircFlag:w
|
||
local ContentPtr:l,NumCells:w,CurCell:w
|
||
local RefType:w,TargetCell:l,TargetCell2:l
|
||
BEGIN
|
||
|
||
stz CircFlag
|
||
|
||
H_GetBlockPtr ContentIndex,ContentPtr
|
||
|
||
lda ContentPtr+2
|
||
ora ContentPtr
|
||
jeq Exit
|
||
|
||
MoveWord [ContentPtr]:#E_FormulaCells,NumCells
|
||
MoveWord #E_FormulaData,CurCell
|
||
cmp NumCells
|
||
jge Exit
|
||
|
||
loop
|
||
MoveWord [ContentPtr]:CurCell,a
|
||
and #$00FF
|
||
sta RefType
|
||
|
||
and #$0080
|
||
jeq singleRef
|
||
|
||
iny
|
||
in [ContentPtr]:y:l,RefType:w,Cell:l
|
||
out TargetCell:l
|
||
XCall S_GetRealCell
|
||
|
||
AddWord CurCell,#5,CurCell
|
||
tay
|
||
|
||
MoveWord [ContentPtr]:y,a
|
||
and #$00FF
|
||
sta RefType
|
||
|
||
iny
|
||
in [ContentPtr]:y:l,RefType:w,Cell:l
|
||
out TargetCell2:l
|
||
XCall S_GetRealCell
|
||
|
||
Call S_NormalizeRange,in=(TargetCell:l,TargetCell2:l)
|
||
|
||
in #S_IsCellCircular:l ; 2 inputs already on stack
|
||
XCall S_TraverseRange
|
||
|
||
bcc nextCell
|
||
bra setCircFlag
|
||
|
||
singleRef
|
||
iny
|
||
in [ContentPtr]:y:l,RefType:w,Cell:l
|
||
out TargetCell:l
|
||
XCall S_GetRealCell
|
||
|
||
Call S_IsCellCircular,in=(TargetCell:l)
|
||
bcc nextCell
|
||
|
||
setCircFlag
|
||
MoveWord #S_CellCircular,CircFlag
|
||
bra Exit
|
||
|
||
nextCell
|
||
AddWord CurCell,#5,CurCell
|
||
cmp NumCells
|
||
bge Exit
|
||
brl loop
|
||
|
||
Exit
|
||
RETURN
|
||
ENDP
|
||
END
|
||
|