antoine-source/appleworksgs/SS/Src/Move3.aii
2023-03-04 03:45:20 +01:00

1 line
17 KiB
Plaintext
Executable File

LOAD 'Macros.dump'
INCLUDE 'SS.equ'
INCLUDE 'Driver.equ'
INCLUDE 'Heap.aii.i'
INCLUDE 'Eval.aii.i'
;-----------------------------------------------
;
; Imported addresses
;
;-----------------------------------------------
IMPORT S_AddCellToChangedList
IMPORT S_DeltaMove
IMPORT S_FixFormula
IMPORT S_FixFormula2
IMPORT S_FixFormula3
IMPORT S_FixFormulaFlag
IMPORT S_GetCellTableEntry
IMPORT S_InsertLeftPadCells
IMPORT S_InsertRightPadCells
IMPORT S_MergeDependLists
IMPORT S_MoveDestBR
IMPORT S_MoveDestTL
IMPORT S_MoveNewCell
IMPORT S_MoveOldCell
IMPORT S_MoveSrcBR
IMPORT S_MoveSrcTL
IMPORT S_RearrangePadCells
IMPORT S_RemoveCellFromChangedList
IMPORT S_ResetCircularity
IMPORT S_SetCellTableEntry
IMPORT S_SetCircularBits
IMPORT S_SplitDependList
IMPORT S_TraverseDependFormulas
;-----------------------------------------------
;
; Forward addresses and entries
;
;-----------------------------------------------
ENTRY S_ClearChangedBits
ENTRY S_ClearChangedBits2
;--------------------------------------------------------------------------
; S_SwapCell
;
; For the purposes of the comments in this routine, the following
; terminology will be used. User cell's are those cells that the user
; thinks of as cells. (These include labels, values, and 2 types of formulas.
; The cell type of user cells are always positive, and of non-user cells are
; always negative.) Pad cells are those cell structures in the cell table, used
; to indicate space for overlapping labels. Real cells will be the union of
; User and Pad cells. (This name is used because real cell structures exist.)
; Fake cells are cell table entries that consist of dependency lists.
; (Dependency lists always have some of the high 2 bits of the cell table entry
; non-zero for detection.) Empty cells are blank cell table entries. (For the
; purposes of this routine, empty cells treated as Fake cells because the
; code works.)
S_SwapCell PROC EXPORT
;Using S_CurrentData
;Using S_MoveData
;Using S_SwapCellFixData
input SrcCell:l
local SrcCellTableEntry:l,SrcFakeFlag:w
local SrcFormat:l,SrcCellType:w
local SrcFormulaIndex:l,SrcDependIndex:l
local SrcSingDepList:l,SrcRngDepList:l
local NewSrcEntry:l,NewSrcDepList:l
local DestCell:l,DestCellTableEntry:l,DestFakeFlag:w
local DestFormat:l,DestCellType:w
local DestFormulaIndex:l,DestDependIndex:l
local DestSingDepList:l,DestRngDepList:l
local NewDestEntry:l,NewDestDepList:l
local CellPtr:l,PreviousCell:l,NextCell:l,ClrChangedBits:w
error ErrorFlag
BEGIN
; Initialize flag variables
stz ErrorFlag
stz SrcFakeFlag
stz DestFakeFlag
stz ClrChangedBits
; Determine the other cell to swap with
AddWord SrcCell,S_DeltaMove,DestCell
AddWord SrcCell+2,S_DeltaMove+2,DestCell+2
; ;
; Adjust the src cell ;
; ;
in SrcCell:l
out SrcCellTableEntry:l
XCall S_GetCellTableEntry
ora SrcCellTableEntry
beq fakeSrc1 ; branch empty cell
lda SrcCellTableEntry+2
and #S_CellTableFlags
beq realSrc1 ; branch real cell
; The following works for both fake and empty src cells.
fakeSrc1
inc SrcFakeFlag
MoveWord #S_CellTypeEmpty,SrcCellType
MoveWord #0,SrcFormat+2
MoveLong SrcCellTableEntry,SrcDependIndex
brl adjustDestCell
realSrc1
H_GetBlockPtr SrcCellTableEntry,CellPtr
MoveLong [CellPtr]:#S_CellContent,SrcFormulaIndex
MoveLong [CellPtr]:#S_CellDependOnMe,SrcDependIndex
MoveLong [CellPtr]:#S_CellFormat,SrcFormat
MoveLong [CellPtr]:#S_CellNext,NextCell
MoveLong [CellPtr]:#S_CellPrevious,PreviousCell
lda SrcFormat+2
and #$FFFF-S_CellCircular
MoveWord a,[CellPtr]:#S_CellFormat+2
lda SrcFormat
and #S_CellType
sta SrcCellType
bmi chkChangedSrc ; branch pad cell
; Clear any circularity, we'll reset them at the end ;
userSrc1
lda SrcFormat+2
and #S_CellCircular
beq chkChangedSrc
Call S_ResetCircularity,in=(SrcCell:l)
; Remove SrcCell from changed list if it is already there. ;
chkChangedSrc
lda NextCell+2
ora NextCell
beq adjustDestCell
lda #0
MoveWord a,[CellPtr]:#S_CellNext
MoveWord a,[CellPtr]:#S_CellNext+2
MoveWord a,[CellPtr]:#S_CellPrevious
MoveWord a,[CellPtr]:#S_CellPrevious+2
in SrcCell:l,PreviousCell:l,NextCell:l
XCall S_RemoveCellFromChangedList
; ;
; Adjust the dest cell ;
; ;
adjustDestCell
in DestCell:l
out DestCellTableEntry:l
XCall S_GetCellTableEntry
ora DestCellTableEntry
beq fakeDest ; branch empty cell
lda DestCellTableEntry+2
and #S_CellTableFlags
beq realDest1 ; branch real cell
; The following works for both fake and empty Dest cells.
fakeDest
inc DestFakeFlag
MoveWord #S_CellTypeEmpty,DestCellType
MoveWord #0,DestFormat+2
MoveLong DestCellTableEntry,DestDependIndex
brl adjustDepends
realDest1
H_GetBlockPtr DestCellTableEntry,CellPtr
MoveLong [CellPtr]:#S_CellContent,DestFormulaIndex
MoveLong [CellPtr]:#S_CellDependOnMe,DestDependIndex
MoveLong [CellPtr]:#S_CellFormat,DestFormat
MoveLong [CellPtr]:#S_CellNext,NextCell
MoveLong [CellPtr]:#S_CellPrevious,PreviousCell
lda DestFormat+2
and #$FFFF-S_CellCircular
MoveWord a,[CellPtr]:#S_CellFormat+2
lda DestFormat
and #S_CellType
sta DestCellType
bmi chkChangedDest ; branch pad cell
; Clear any circularity, we'll reset them at the end ;
userDest
lda DestFormat+2
and #S_CellCircular
beq chkChangedDest
Call S_ResetCircularity,in=(DestCell:l)
; Remove DestCell from changed list if it is already there.
chkChangedDest
lda NextCell+2
ora NextCell
beq adjustDepends
lda #0
MoveWord a,[CellPtr]:#S_CellNext
MoveWord a,[CellPtr]:#S_CellNext+2
MoveWord a,[CellPtr]:#S_CellPrevious
MoveWord a,[CellPtr]:#S_CellPrevious+2
in DestCell:l,PreviousCell:l,NextCell:l
XCall S_RemoveCellFromChangedList
; Adjust src cell's DependOnMe references
adjustDepends
lda SrcDependIndex
ora SrcDependIndex+2
beq adjustDestDep
; Set up the globals used in the FixFormula routines
stz S_FixFormulaFlag
MoveLong SrcCell,S_MoveOldCell
MoveLong DestCell,S_MoveNewCell
; The first changed bit allows for formulas with references to
; both cells involved, and the Fix routines will still work.
; The second changed bit allows for circular references to itself.
lda DestDependIndex
ora DestDependIndex+2
beq doFixFormFlag1
MoveWord #S_RecentlyChangedBit,S_FixFormulaFlag
inc ClrChangedBits
doFixFormFlag1
lda SrcFormat+2
and #S_CellCircular
beq doTraverse1
lda #S_RecentlyChangedBit2
tsb S_FixFormulaFlag
inc ClrChangedBits
doTraverse1
in SrcCell:l,SrcCellTableEntry:l
in #S_FixFormula:l,#S_FixFormula2:l
XCall S_TraverseDependFormulas
; Adjust dest cell's DependOnMe references
adjustDestDep
lda DestDependIndex
ora DestDependIndex+2
beq adjustFormulas
stz S_FixFormulaFlag
MoveLong DestCell,S_MoveOldCell
MoveLong SrcCell,S_MoveNewCell
lda DestFormat+2
and #S_CellCircular
beq doTraverse2
MoveWord #S_RecentlyChangedBit2,S_FixFormulaFlag
inc ClrChangedBits
doTraverse2
in DestCell:l,DestCellTableEntry:l
in #S_FixFormula:l,#S_FixFormula2:l
XCall S_TraverseDependFormulas
; Adjust src cell's formula ;
adjustFormulas
lda SrcCellType
bmi adjustDestFormula ; branch non-user cell
and #S_CellTypeTextForm
beq adjustDestFormula ; branch non-formula cell
MoveLong SrcCell,S_MoveOldCell
MoveLong DestCell,S_MoveNewCell
in SrcCell:l,DestCell:l,SrcFormulaIndex:l
XCall S_FixFormula3
; Adjust dest cell's formula ;
adjustDestFormula
lda DestCellType
bmi chkClrChangedBits ; branch non-user cell
and #S_CellTypeTextForm
beq chkClrChangedBits ; branch non-formula cell
MoveLong DestCell,S_MoveOldCell
MoveLong SrcCell,S_MoveNewCell
in DestCell:l,SrcCell:l,DestFormulaIndex:l
XCall S_FixFormula3
chkClrChangedBits
lda SrcFakeFlag
beq chkClrChgBits2 ; branch real cell
in SrcCell:l
out :l
XCall S_GetCellTableEntry
pla
sta SrcCellTableEntry
sta SrcDependIndex
pla
sta SrcCellTableEntry+2
sta SrcDependIndex+2
ora SrcCellTableEntry
beq chkClrDest ; branch empty cell
chkClrChgBits2
lda ClrChangedBits
beq chkClrDest
in SrcCell:l,SrcCellTableEntry:l
in #S_ClearChangedBits:l,#S_ClearChangedBits2:l
XCall S_TraverseDependFormulas
lda SrcCellType
bmi chkClrDest ; branch non-user cell
and #S_CellTypeTextForm
beq chkClrDest ; branch non-formula cell
Call S_ClearChangedBits,in=(SrcCell:l,SrcFormulaIndex:l)
chkClrDest
lda DestFakeFlag
beq chkClrDest2 ; branch real cell
in DestCell:l
out :l
XCall S_GetCellTableEntry
pla
sta DestCellTableEntry
sta DestDependIndex
pla
sta DestCellTableEntry+2
sta DestDependIndex+2
ora DestCellTableEntry
beq doSwap ; branch empty cell
chkClrDest2
lda ClrChangedBits
beq doSwap
in DestCell:l,DestCellTableEntry:l
in #S_ClearChangedBits:l,#S_ClearChangedBits2:l
XCall S_TraverseDependFormulas
lda DestCellType
bmi doSwap ; branch non-user cell
and #S_CellTypeTextForm
beq doSwap ; branch non-formula cell
Call S_ClearChangedBits,in=(DestCell:l,DestFormulaIndex:l)
; Break up both depend lists into their single cell and range parts.
; The old single part will be attached to New location's range part
; and vise - versa.
doSwap
lda SrcFakeFlag
bne splitSrcDeps ; branch fake or empty cell
H_GetBlockPtr SrcCellTableEntry,CellPtr
MoveLong [CellPtr]:#S_CellDependOnMe,SrcDependIndex
; Split up the depend list. ;
splitSrcDeps
in SrcDependIndex:l
out SrcSingDepList:l,SrcRngDepList:l
XCall S_SplitDependList
; Now break up the dest depend lists into its single cell and range parts.
lda DestFakeFlag
bne splitDestDeps ; branch fake or empty cell
H_GetBlockPtr DestCellTableEntry,CellPtr
MoveLong [CellPtr]:#S_CellDependOnMe,DestDependIndex
splitDestDeps
in DestDependIndex:l
out DestSingDepList:l,DestRngDepList:l
XCall S_SplitDependList
; Merge the Src's SingDepList with the Dest's RngDepList list
in SrcSingDepList:l,DestRngDepList:l
out NewDestDepList:l
XCall S_MergeDependLists
; Merge the Dest's SingDepList with the Src's RngDepList list
in DestSingDepList:l,SrcRngDepList:l
out NewSrcDepList:l
XCall S_MergeDependLists
; The following 3 labels represent the 3 ways to set up
; the NewSrcEntry used in this swap.
; 1) Nothing left in the Src cell. Set the depend list here.
; The New src is fake.
; 2) Pad Cell left in the Src position. Put the depend
; in the pad cell.
; 3) The Dest was user and is moving to the Src postion. Set the
; depend in the user cell.
lda DestCellType
bpl userSrc5 ; branch all <-> user
lda SrcFakeFlag
bne fakeSrc5 ; branch empty,fake <-> empty,fake,pad
lda SrcCellType
bmi padSrc5 ; branch pad <-> empty,fake,pad
lda DestFakeFlag
bne fakeSrc5 ; branch user <-> empty,fake
; A User Src is moving to a Pad Dest. The pad must be disposed of.
; A fake Src is left behind.
; Call S_RemoveCell,in=(DestCell:l)
H_DisposeBlock DestCellTableEntry
; The following 9 cases get to the following code.
; empty,fake,user <-> empty,fake,pad
fakeSrc5
MoveLong NewSrcDepList,NewSrcEntry
lda SrcCellType
jpl userDest6 ; branch user <-> empty,fake,pad
lda DestFakeFlag
jne fakeDest6 ; branch empty,fake <-> empty,fake
brl padDest6 ; branch empty,fake <-> pad
;-------------------------------------
; The following 3 cases get to the following code.
; pad <-> empty,fake,pad
padSrc5
H_GetBlockPtr SrcCellTableEntry,CellPtr
MoveLong NewSrcDepList,[CellPtr]:#S_CellDependOnMe
MoveLong SrcCellTableEntry,NewSrcEntry
lda DestFakeFlag
bne fakeDest6 ; branch pad <-> empty,fake
bra padDest6 ; branch pad <-> pad
;-------------------------------------
; The following 4 cases get to the following code.
; all <-> user
userSrc5
H_GetBlockPtr DestCellTableEntry,CellPtr
MoveLong SrcCell,[CellPtr]:#S_CellID
MoveLong NewSrcDepList,[CellPtr]:#S_CellDependOnMe
MoveLong DestCellTableEntry,NewSrcEntry
lda SrcFakeFlag
bne fakeDest6 ; branch empty,fake <-> user
lda SrcCellType
bpl userDest6 ; branch user <-> user
; A User Dest is moving to a Pad Src. The pad must be disposed of.
; A fake Dest is left behind.
; Call S_RemoveCell,in=(SrcCell:l)
H_DisposeBlock SrcCellTableEntry
; The following 3 labels represent the 3 ways to set up
; the NewDestEntry used in this swap.
; 1) Nothing left in the Dest cell. Set the depend list here.
; The New Dest is fake.
; 2) Pad Cell left in the Dest position. Put the depend
; in the pad cell.
; 3) The Src was real and is moving to the Dest postion. Set the
; depend in the real cell.
; The following 9 cases get to the following code.
; empty,fake,pad <-> empty,fake,user
fakeDest6
MoveLong NewDestDepList,NewDestEntry
bra resetIndices
;-------------------------------------
; The following 3 cases get to the following code.
; empty,fake,pad <-> pad
padDest6
H_GetBlockPtr DestCellTableEntry,CellPtr
MoveLong NewDestDepList,[CellPtr]:#S_CellDependOnMe
MoveLong DestCellTableEntry,NewDestEntry
bra resetIndices
;-------------------------------------
; The following 4 cases get to the following code.
; user <-> all
userDest6
H_GetBlockPtr SrcCellTableEntry,CellPtr
MoveLong DestCell,[CellPtr]:#S_CellID
MoveLong NewDestDepList,[CellPtr]:#S_CellDependOnMe
MoveLong SrcCellTableEntry,NewDestEntry
;-------------------------------------
; The following 16 cases get to the following code.
; all <-> all
resetIndices
Call S_SetCellTableEntry,in=(SrcCell:l,NewSrcEntry:l)
Call S_SetCellTableEntry,in=(DestCell:l,NewDestEntry:l)
; If cells are labels, fix pad cells: if cells are formulas, fix
; circularity
lda SrcCellType
bpl chkSrcCirc
lda DestCellType
bpl chkDestCirc
brl chkSrcChanged
chkSrcCirc
and #S_CellTypeTextForm
beq chkDestCircCheck
Call S_SetCircularBits,in=(DestCell:l)
chkDestCircCheck
lda DestCellType
bmi fixSrcPadCells
chkDestCirc
and #S_CellTypeTextForm
beq fixSrcPadCells
Call S_SetCircularBits,in=(SrcCell:l)
; Remove old pad cells ;
fixSrcPadCells
in DestCell:l
out :l,:l
XCall S_RearrangePadCells,err=ErrorFlag
pla
plx
cpx S_MoveDestBR+2
blt chkLeft1
stx S_MoveDestBR+2
chkLeft1
pla
plx
cpx S_MoveDestTL+2
bge fixDestPadCells
stx S_MoveDestTL+2
fixDestPadCells
lda ErrorFlag
jne chkSrcChanged
in SrcCell:l
out :l,:l
XCall S_RearrangePadCells,err=ErrorFlag
pla
plx
cpx S_MoveSrcBR+2
blt chkLeft2
stx S_MoveSrcBR+2
chkLeft2
pla
plx
cpx S_MoveSrcTL+2
bge chkSrcLabel
stx S_MoveSrcTL+2
; Insert New pad cells ;
chkSrcLabel
lda ErrorFlag
bne chkSrcChanged
lda SrcCellType
bne chkDestLabel ; 0 = label
Call S_InsertRightPadCells,in=(DestCell:l),out=(ax:l)
cpx S_MoveDestBR+2
blt chkLeft3
stx S_MoveDestBR+2
chkLeft3
Call S_InsertLeftPadCells,in=(DestCell:l),out=(ax:l)
cpx S_MoveDestTL+2
bge chkDestLabel
stx S_MoveDestTL+2
chkDestLabel
lda DestCellType
bne chkSrcChanged ; 0 = label
Call S_InsertRightPadCells,in=(SrcCell:l),out=(ax:l)
cpx S_MoveSrcBR+2
blt chkLeft4
stx S_MoveSrcBR+2
chkLeft4
Call S_InsertLeftPadCells,in=(SrcCell:l),out=(ax:l)
cpx S_MoveSrcTL+2
bge chkSrcChanged
stx S_MoveSrcTL+2
chkSrcChanged
lda DestCellTableEntry
ora DestCellTableEntry+2
beq chkDestChanged
Call S_AddCellToChangedList,in=(SrcCell:l)
chkDestChanged
lda SrcCellTableEntry
ora SrcCellTableEntry+2
beq Exit
Call S_AddCellToChangedList,in=(DestCell:l)
Exit RETURN
ENDP
;---------------------------------------------------------------------------
;
; These routines clear the S_CellChangedBit of the cell reference's
; refbytes.
S_ClearChangedBits PROC EXPORT
;Using S_CurrentData
input Cell:l,FormulaIndex:l
local FormulaPtr:l
local Start:w,Stop:w
BEGIN
H_GetBlockPtr FormulaIndex,FormulaPtr
MoveWord [FormulaPtr]:#E_FormulaCells,Stop
MoveWord #E_FormulaData,Start
bra chkEnd
dependLoop
MoveWord [FormulaPtr]:Start,a
and #$FFFF-S_RecentlyChangedBit-S_RecentlyChangedBit2
sta [FormulaPtr],y
AddWord Start,#5,Start
chkEnd
cmp Stop
blt dependLoop
RETURN #0
ENDP
;----------------------------------------------------------------------------
;
;
S_ClearChangedBits2 PROC EXPORT
input Cell:l,FormulaIndex:l
output Moved:w
BEGIN
stz Moved
Call S_ClearChangedBits,in=(Cell:l,FormulaIndex:l)
RETURN Moved
ENDP
END