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