
		LOAD		'Macros.dump'
		INCLUDE	'M16.Profile'

		INCLUDE	'SS.equ'

;		INCLUDE	'Driver.equ'
		INCLUDE	'Heap.aii.i'
		INCLUDE	'Eval.aii.i'

;-----------------------------------------------
;
;	Imported addresses
;
;-----------------------------------------------

		IMPORT	S_AcceptCell
		IMPORT	S_AddCellToChangedList
		IMPORT	S_BuildTrashUndo
		IMPORT	S_DeltaMove
		IMPORT	S_DependHomeCell
		IMPORT	S_FixDependList
		IMPORT	S_GetCellTableEntry
		IMPORT	S_GetRealCell
		IMPORT	S_GetRefCell
		IMPORT	S_InRange
		IMPORT	S_MoveCell
		IMPORT	S_MoveDestBR
		IMPORT	S_MoveDestTL
		IMPORT	S_MoveOldCell
		IMPORT	S_MoveSrcTL
		IMPORT	S_NormalizeRange
		IMPORT	S_OrigTransDestBR
		IMPORT	S_OrigTransDestTL
		IMPORT	S_RemoveRangeDep
		IMPORT	S_ResetCircularity
		IMPORT	S_SetCellTableEntry
		IMPORT	S_SetCircularBits
		IMPORT	S_SplitDependList
		IMPORT	S_SwapCell
		IMPORT	S_TraverseDependFormulas
		IMPORT	S_TraverseRange

;-----------------------------------------------
;
;	Forward addresses and entries
;
;-----------------------------------------------

		ENTRY	S_TrashFormula
		ENTRY	S_TrashFormula2

;-------------------------------------------------------------------------
;
;

S_TrashCell	PROC		EXPORT
			;Using	S_CurrentData
			;Using	S_MoveData

			input	Cell:l,CellTableEntry:l
			local	DependList:l,DependPtr:l
			local	CellPtr:l,FakeCellFlag:w
			local	SingleList:l,RangeList:l
			local	RangeStart:l,RangeSize:l
			error	ErrFlag
			BEGIN

	ProfileIn		1

			stz		ErrFlag

	;	We know that there is something at this location.  If it is only
	;	a depend list, we can skip the first part of this routine.

			lda		CellTableEntry+2
			and		#S_CellTableFlags
			sta		FakeCellFlag
			bne		doTrashTraverse

	;	If a user-cell exists, we will first remove the cell (as if with
	;	a delete key). This will clean up any depend ptrs to this cell as
	;	well as fix up any pad cells.

			ldx		#S_CellTypeEmpty
			in		Cell:l,x:w,x:w,x:w,x:w
			out		:l,:l
			XCall	S_AcceptCell,err=ErrFlag

			pla
			plx

			cpx		S_MoveDestBR+2
			blt		chkLeft1

			stx		S_MoveDestBR+2

chkLeft1
			pla
			plx

			cpx		S_MoveDestTL+2
			bge		getIndex

			stx		S_MoveDestTL+2

getIndex
			lda		ErrFlag
			jne		Exit

	;	Now if there are any depend ptrs left at this location, we need to
	;	'trash' the formulas that refer to this cell.  First get the depend list.
	;	

			Call		S_GetCellTableEntry,in=(Cell:l),out=(CellTableEntry:l)

			ora		CellTableEntry
			jeq		Exit

			lda		CellTableEntry+2
			and		#S_CellTableFlags
			sta		FakeCellFlag

	;	This will traverse the depend list and trash any cells that refer
	;	to this cell.

doTrashTraverse
			MoveLong	Cell,S_MoveOldCell

			in		Cell:l,CellTableEntry:l,#S_TrashFormula:l,#S_TrashFormula2:l
			XCall	S_TraverseDependFormulas,err=ErrFlag
			jcs		Exit

	;	Get the DependList again.  It could have changed, because trashing an
	;	endpt of a range will modify depend lists.

			lda		FakeCellFlag
			beq		doRealCell

			Call		S_GetCellTableEntry,in=(Cell:l),out=(DependList:l)
			bra		gotDepList

doRealCell
			H_GetBlockPtr	CellTableEntry,CellPtr

			MoveWord	[CellPtr]:#S_CellDependOnMe,DependList
			MoveWord	[CellPtr]:#S_CellDependOnMe+2,DependList+2

	;	If nothing left, quit.

gotDepList
			ora		DependList
			bne		gotDepList2

			bra		Exit

	;	Else, keep only the range part of the list.  To do this we need
	;	to split up the list and Save the range part at the cell.  We'll
	;	throw away the single part.

gotDepList2
			in		DependList:l
			out		SingleList:l,RangeList:l
			XCall	S_SplitDependList,err=ErrFlag

			bcs		Exit

	;	Save the range part.

			lda		FakeCellFlag
			beq		doPadCell2

			Call		S_SetCellTableEntry,in=(Cell:l,RangeList:l)
			bra		depListSet

doPadCell2
			H_GetBlockPtr	CellTableEntry,CellPtr

			MoveWord	RangeList,[CellPtr]:#S_CellDependOnMe
			MoveWord	RangeList+2,[CellPtr]:#S_CellDependOnMe+2

	;	Throw away the single part.

depListSet
			lda		SingleList+2
			bmi		Exit

			and		#$FFFF-S_CellTableFlags
			sta		SingleList+2

			ora		SingleList
			beq		Exit

			H_DisposeBlock	SingleList

Exit

	ProfileOut	1

			RETURN
			ENDP

;----------------------------------------------------------------------------
;
;

S_TrashFormula	PROC		EXPORT
			;Using	S_CurrentData
			;Using	S_MoveData

			input	DependCell:l,FormulaIndex:l
			local	FormulaPtr:l,Start:w,Stop:w,RealCell:l
			error	ErrFlag
			BEGIN

			stz		ErrFlag

			Call		S_AddCellToChangedList,in=(DependCell:l)

			in		DependCell:l,FormulaIndex:l
			XCall	S_BuildTrashUndo,err=ErrFlag
			jcs		Exit

			H_GetBlockPtr	FormulaIndex,FormulaPtr

			MoveWord	[FormulaPtr]:#E_FormulaCells,Stop
			MoveWord	#E_FormulaData,Start

	;	No need to check first, a DependOnMe pointer assures at least
	;	one cell in formula

dependLoop
			MoveWord	[FormulaPtr]:Start,a
			and		#$0080
			jne		notSingleCell

			SpaceLong
			AddWord	Start,#3,y
			PushWord	[FormulaPtr]:y
			dey
			dey
			PushWord	[FormulaPtr]:y
			dey
			lda		[FormulaPtr],y
			and		#$00FF
			pha
			PushLong	DependCell
			Call		S_GetRealCell
			PullLong	RealCell

			CmpLong	RealCell,S_MoveOldCell
			bne		nextDepend

			ldy		Start
			iny

			MoveLong	#S_NotACell,[FormulaPtr]:y


nextDepend
			AddWord	Start,#5,Start
			bra		cmpEnd

notSingleCell
			AddWord	Start,#10,Start

cmpEnd
			CmpWord	Start,Stop
			jlt		dependLoop

Exit
			RETURN
			ENDP

;----------------------------------------------------------------------------
;
;

S_TrashFormula2	PROC		EXPORT
				;Using	S_CurrentData
				;Using	S_MoveData
				;Using	S_DependData

			input	DependCell:l,FormulaIndex:l
			output	Moved:w
			local	FormulaPtr:l,Stop:w,Start:w
			local	RealCell:l,RealCell2:l,WhichEnd:w
			error	ErrFlag
			BEGIN

			stz		ErrFlag
			stz		Moved

			Call		S_AddCellToChangedList,in=(DependCell:l)

			H_GetBlockPtr	FormulaIndex,FormulaPtr

			MoveWord	[FormulaPtr]:#E_FormulaCells,Stop
			MoveWord	#E_FormulaData,Start

	;	No need to check first, a DependOnMe pointer assures at least
	;	one cell in formula

dependLoop
			MoveWord	[FormulaPtr]:Start,a
			and		#$0080
			jeq		notRange

			SpaceLong
			AddWord	Start,#3,y
			PushWord	[FormulaPtr]:y
			dey
			dey
			PushWord	[FormulaPtr]:y
			dey
			lda		[FormulaPtr],y
			and		#$00FF
			pha
			PushLong	DependCell
			Call		S_GetRealCell
			PullLong	RealCell

			SpaceLong
			AddWord	Start,#8,y
			PushWord	[FormulaPtr]:y
			dey
			dey
			PushWord	[FormulaPtr]:y
			dey
			lda		[FormulaPtr],y
			and		#$00FF
			pha
			PushLong	DependCell
			Call		S_GetRealCell
			PullLong	RealCell2

			CmpLong	RealCell,S_MoveOldCell
			beq		doAdjust1

			CmpLong	RealCell2,S_MoveOldCell
			jne		nextDepend

			MoveWord	#1,WhichEnd
			bra		doAdjust

doAdjust1
			stz		WhichEnd

doAdjust
			MoveLong	DependCell,S_DependHomeCell

			Call		S_NormalizeRange,in=(RealCell:l,RealCell2:l)

			in		#S_RemoveRangeDep:l			; 2 inputs already on stack
			XCall	S_TraverseRange


			in		DependCell:l,FormulaIndex:l
			XCall	S_BuildTrashUndo,err=ErrFlag
			bcs		Exit

			H_GetBlockPtr	FormulaIndex,FormulaPtr

			lda		WhichEnd
			bne		doSecond

			ldy		Start
			iny
			bra		fixRange

doSecond
			AddWord	Start,#6,y

fixRange
			MoveLong	#S_NotACell,[FormulaPtr]:y
			inc		Moved

nextDepend
			AddWord	Start,#10,Start
			bra		cmpEnd

notRange
			AddWord	Start,#5,Start

cmpEnd
			CmpWord	Start,Stop
			jlt		dependLoop

			lda		Moved
			beq		Exit

			Call		S_ResetCircularity,in=(DependCell:l)
			Call		S_SetCircularBits,in=(DependCell:l)

Exit
			RETURN
			ENDP

;-------------------------------------------------------------------------
;
;

S_TransposeCell	PROC		EXPORT
				;Using	S_MoveData

			input	SrcCell:l
			local	DestCell:l,SrcIndex:l
			error	ErrorFlag
			BEGIN

			stz		ErrorFlag

			SubWord	SrcCell+2,S_MoveSrcTL+2,a
			AddWord	a,S_MoveSrcTL,DestCell

			SubWord	SrcCell,S_MoveSrcTL,a
			AddWord	a,S_MoveSrcTL+2,DestCell+2

			SubWord	DestCell,SrcCell,S_DeltaMove
			SubWord	DestCell+2,SrcCell+2,S_DeltaMove+2

			in		S_OrigTransDestTL:l,S_OrigTransDestBR:l,SrcCell:l
			out		a:w
			XCall	S_InRange

			beq		notInRange

			lda		S_DeltaMove+2			; note: during a transpose
			bpl		Exit					; only one direction is +


			Call		S_SwapCell,in=(SrcCell:l),err=ErrorFlag
			bra		Exit

notInRange
			in		SrcCell:l
			out		SrcIndex:l
			XCall	S_GetCellTableEntry

			ora		SrcIndex
			beq		Exit

			in		SrcCell:l,SrcIndex:l
			XCall	S_MoveCell

Exit
			RETURN
			ENDP

;-------------------------------------------------------------------------
;
;

S_FixFormula3	PROC		EXPORT
			;Using	S_CurrentData

			input	SrcCell:l,DestCell:l,FormulaIndex:l
			local	FormulaPtr:l,Start:w,Stop:w,ChangedBit:w
			local	RefByte:w,RealCell:l,RealCell2:l
			BEGIN

	ProfileIn		6

			H_GetBlockPtr	FormulaIndex,FormulaPtr

			MoveWord	[FormulaPtr]:#E_FormulaCells,Stop
			MoveWord	#E_FormulaData,Start
			brl		chkDone

formLoop
			SpaceLong
			AddWord	Start,#3,y
			PushWord	[FormulaPtr]:y
			dey
			dey
			PushWord	[FormulaPtr]:y
			dey
			lda		[FormulaPtr],y
			and		#$00FF
			sta		RefByte
			pha

			and		#S_RecentlyChangedBit2
			sta		ChangedBit

			PushLong	SrcCell
			Call		S_GetRealCell
			PullLong	RealCell

			Call		S_GetRefCell,in=(RealCell:l,RefByte:w,DestCell:l)
			PullWord	[FormulaPtr]:Start
			iny
			PullLong	[FormulaPtr]:y

			AddWord	Start,#5,Start


;	;	This will fix some circularity problems	;
;
;	lda	ChangedBit
;	beq	cont1
;
;	CmpLong	RealCell,DestCell
;	bne	cont1
;
;	MoveLong	SrcCell,RealCell
;ont1	anop



			lda		RefByte
			and		#$0080
			jeq		singleRef


			SpaceLong
			AddWord	Start,#3,y
			PushWord	[FormulaPtr]:y
			dey
			dey
			PushWord	[FormulaPtr]:y
			dey
			lda		[FormulaPtr],y
			and		#$00FF
			sta		RefByte
			pha

			and		#S_RecentlyChangedBit2
			sta		ChangedBit

			PushLong	SrcCell
			Call		S_GetRealCell
			PullLong	RealCell2

			Call		S_GetRefCell,in=(RealCell2:l,RefByte:w,DestCell:l)
			PullWord	[FormulaPtr]:Start
			iny
			PullLong	[FormulaPtr]:y

			AddWord	Start,#5,Start


;	;	This will fix some circularity problems	;
;
;	lda	ChangedBit
;	beq	cont2
;
;	CmpLong	RealCell2,DestCell
;	bne	cont2
;
;	MoveLong	SrcCell,RealCell2
;ont2	anop


			Call		S_NormalizeRange,in=(RealCell:l,RealCell2:l)

			in		#S_FixDependList:l			; 2 inputs on stack
			XCall	S_TraverseRange

			bra		chkDone

	;	This will fix some circularity problems

	;	The first fix solves the problem of the dest cell refering
	;	to the src cell, in which case the depend list is at the dest
	;	cell, but the src formula is being changed.

singleRef
			CmpLong	RealCell,SrcCell
			bne		cont4

			MoveLong	DestCell,RealCell
			bra		cont3

	;	This solves the problem of cell that refers (singly) to itself.
	;	The depend list is at the src cell, but the formula
	;	is already changed.

cont4
			lda		ChangedBit
			beq		cont3

			CmpLong	RealCell,DestCell
			bne		cont3

			MoveLong	SrcCell,RealCell
cont3

			Call		S_FixDependList,in=(RealCell:l)

chkDone
			CmpWord	Start,Stop
			jlt		formLoop

	ProfileOut	6

			RETURN
			ENDP
			END

