LOAD 'Macros.dump' INCLUDE 'SS.equ' INCLUDE 'Driver.equ' INCLUDE 'Heap.aii.i' ;----------------------------------------------- ; ; Imported addresses ; ;----------------------------------------------- IMPORT D_AlertBox IMPORT D_CmpStrings IMPORT D_MemoryError IMPORT D_NeedHand IMPORT D_Sort IMPORT S_ActiveWindow IMPORT S_BuildSortUndo IMPORT S_CalculateSheet IMPORT S_CurBRMost IMPORT S_CurBRSelect IMPORT S_CurEditFlag IMPORT S_CurRowBlock IMPORT S_CurTLSelect IMPORT S_DeltaMove IMPORT S_DoSortDlog IMPORT S_GetCellIndex IMPORT S_InvalidCellStr IMPORT S_MoveDestBR IMPORT S_MoveDestTL IMPORT S_MoveSrcBR IMPORT S_MoveSrcTL IMPORT S_RedrawCellRange IMPORT S_SetBRMostCell IMPORT S_SetUndoOn IMPORT S_StartSortUndo IMPORT S_SwapCell IMPORT S_SwapIn ;----------------------------------------------- ; ; Forward addresses and entries ; ;----------------------------------------------- ENTRY S_DoColSort ENTRY S_DoRowSort ENTRY S_SortCompare ENTRY S_SwapColumns ENTRY S_SwapRows ;------------------------------------------------------------------------- ; ; S_SortData PROC EXPORT EXPORT S_SortAscendDescendFlag S_SortAscendDescendFlag DS.B 2 ENDP ;-------------------------------------------------------------------------- ; ; S_Sort PROC EXPORT ;Using S_CurrentData ;Using S_SortData ;Using S_MoveData ;Using S_ErrorData local KeyCell:l,Type:w error ErrFlag BEGIN +b Call S_SwapIn,in=(S_ActiveWindow:l) ; ascend: 0==decending,1==ascending ; rowcol: 0==col by row,1==row by col ; cell: 0 == Cancelled, 0 w/carry set == error in S_CurTLSelect:l out S_SortAscendDescendFlag:w,Type:w,KeyCell:l XCall S_DoSortDlog bcc doOK Call D_AlertBox,in=(#OKBox:w,#S_InvalidCellStr:l),out=(a:w) doOK lda KeyCell ora KeyCell+2 jeq Exit lda S_CurEditFlag and #S_BRMostBit beq BRset Call S_SetBRMostCell,in=(#0:w) BRset lda #S_BRMostBit tsb S_CurEditFlag MoveWord S_CurTLSelect,S_MoveDestTL sta S_MoveSrcTL MoveWord S_CurTLSelect+2,S_MoveDestTL+2 sta S_MoveSrcTL+2 MoveWord S_CurBRSelect,S_MoveDestBR sta S_MoveSrcBR MoveWord S_CurBRSelect+2,S_MoveDestBR+2 sta S_MoveSrcBR+2 lda Type bne doRowSort doColSort ldx S_CurBRSelect+2 cpx S_CurBRMost+2 blt doCol2 ldx S_CurBRMost+2 doCol2 in S_CurTLSelect:l,x:w,S_CurBRSelect:w,KeyCell:w XCall S_DoColSort,err=ErrFlag bcc redraw bra memError doRowSort ldx S_CurBRSelect cpx S_CurBRMost blt doRow2 ldx S_CurBRMost doRow2 in S_CurTLSelect:l,S_CurBRSelect+2:w,x:w,KeyCell+2:w XCall S_DoRowSort,err=ErrFlag bcc redraw memError Call D_MemoryError redraw CmpWord S_MoveSrcBR+2,S_MoveDestBR+2 blt chkLeft sta S_MoveDestBR+2 chkLeft CmpWord S_MoveSrcTL+2,S_MoveDestTL+2 bge doDraw sta S_MoveDestTL+2 doDraw in S_MoveDestTL:l,S_MoveDestBR:l XCall S_RedrawCellRange Call S_SetUndoOn,in=(#S_UndoSortType:w) lda S_CurEditFlag and #S_ManCalcBit bne Exit Call S_CalculateSheet Exit RETURN ENDP ;----------------------------------------------------------------------------- ; ; S_DoRowSort PROC EXPORT ;Using S_CurrentData input FCol:w,FRow:w,LCol:w,LRow:w,KeyCol:w local ArrayHandle:l,ArrayPtr:l,ArraySize:w,Count:w local ArrayOffset:w,TargOffset:w,CurRow:w,CellPtr:l local TargRow:w,SrcRow:w error ErrorFlag BEGIN stz ErrorFlag SubWord LRow,FRow,a inc a sta Count asl a asl a sta ArraySize in #0:w,ArraySize:w out ArrayHandle:l XCall D_NeedHand,err=ErrorFlag jcs Exit ; Set up the original array, filled with cell indices ; MoveLong [ArrayHandle],ArrayPtr MoveWord FRow,CurRow stz ArrayOffset bra startInit initLoop inc CurRow AddWord ArrayOffset,#4,ArrayOffset startInit in KeyCol:w,CurRow:w out [ArrayPtr]:ArrayOffset:l XCall S_GetCellIndex ldy ArrayOffset ora [ArrayPtr],y bne cmpInit tya sta [ArrayPtr],y iny iny MoveWord #$FF00,[ArrayPtr]:y cmpInit CmpWord CurRow,LRow blt initLoop ; Sort the array ; in #0:w,Count:w,ArrayHandle:l,#S_SortCompare:l XCall D_Sort,err=ErrorFlag jcs memError ; Renumber array for easy sorting ; MoveLong [ArrayHandle],ArrayPtr stz ArrayOffset renumLoop ldy ArrayOffset iny iny lda [ArrayPtr],y bmi cmpRenum H_GetBlockPtr [ArrayPtr]:ArrayOffset,CellPtr SubWord [CellPtr]:#S_CellID,FRow,a asl a asl a MoveWord a,[ArrayPtr]:ArrayOffset cmpRenum AddWord ArrayOffset,#4,ArrayOffset CmpWord ArrayOffset,ArraySize blt renumLoop in #0:w,FCol:w,FRow:w,LCol:w,LRow:w XCall S_StartSortUndo ; Make Spreadsheet reflect the array ; stz CurRow stz ArrayOffset swapLoop MoveLong [ArrayHandle],ArrayPtr MoveWord [ArrayPtr]:ArrayOffset,TargOffset cmp ArrayOffset beq cmpSwapEnd bge doSwap targLoop MoveWord [ArrayPtr]:TargOffset,TargOffset cmp ArrayOffset beq cmpSwapEnd blt targLoop doSwap lsr a lsr a AddWord a,FRow,TargRow AddWord CurRow,FRow,SrcRow in FCol:w,SrcRow:w,LCol:w,TargRow:w XCall S_BuildSortUndo Call S_SwapRows,in=(FCol:w,SrcRow:w,LCol:w,TargRow:w) cmpSwapEnd inc CurRow AddWord ArrayOffset,#4,ArrayOffset CmpWord a,ArraySize blt swapLoop memError Tool _DisposeHandle,in=(ArrayHandle:l) Exit RETURN ENDP ;----------------------------------------------------------------------------- ; ; S_DoColSort PROC EXPORT ;Using S_CurrentData input FCol:w,FRow:w,LCol:w,LRow:w,KeyRow:w local ArrayHandle:l,ArrayPtr:l,ArraySize:w,Count:w local ArrayOffset:w,TargOffset:w,CurCol:w,CellPtr:l local TargCol:w,SrcCol:w error ErrorFlag BEGIN stz ErrorFlag SubWord LCol,FCol,a inc a sta Count asl a asl a sta ArraySize in #0:w,ArraySize:w out ArrayHandle:l XCall D_NeedHand,err=ErrorFlag jcs Exit ; Set up the original array, filled with cell indices ; MoveLong [ArrayHandle],ArrayPtr MoveWord FCol,CurCol stz ArrayOffset bra startInit initLoop inc CurCol AddWord ArrayOffset,#4,ArrayOffset startInit in CurCol:w,KeyRow:w out [ArrayPtr]:ArrayOffset:l XCall S_GetCellIndex ldy ArrayOffset ora [ArrayPtr],y bne cmpInit tya sta [ArrayPtr],y iny iny MoveWord #$FF00,[ArrayPtr]:y cmpInit CmpWord CurCol,LCol blt initLoop ; Sort the array ; in #0:w,Count:w,ArrayHandle:l,#S_SortCompare:l XCall D_Sort,err=ErrorFlag jcs memError ; Renumber array for easy sorting ; MoveLong [ArrayHandle],ArrayPtr stz ArrayOffset renumLoop ldy ArrayOffset iny iny lda [ArrayPtr],y bmi cmpRenum H_GetBlockPtr [ArrayPtr]:ArrayOffset,CellPtr SubWord [CellPtr]:#S_CellID+2,FCol,a asl a asl a MoveWord a,[ArrayPtr]:ArrayOffset cmpRenum AddWord ArrayOffset,#4,ArrayOffset CmpWord ArrayOffset,ArraySize blt renumLoop Call S_StartSortUndo,in=(#1:w,FCol:w,FRow:w,LCol:w,LRow:w) ; Make Spreadsheet reflect the array ; stz CurCol stz ArrayOffset swapLoop MoveLong [ArrayHandle],ArrayPtr MoveWord [ArrayPtr]:ArrayOffset,TargOffset cmp ArrayOffset beq cmpSwap bge doSwap targLoop MoveWord [ArrayPtr]:TargOffset,TargOffset cmp ArrayOffset beq cmpSwap blt targLoop doSwap lsr a lsr a AddWord a,FCol,TargCol AddWord CurCol,FCol,SrcCol in SrcCol:w,FRow:w,TargCol:w,LRow:w XCall S_BuildSortUndo Call S_SwapColumns,in=(SrcCol:w,FRow:w,TargCol:w,LRow:w) cmpSwap inc CurCol AddWord ArrayOffset,#4,ArrayOffset CmpWord a,ArraySize blt swapLoop memError Tool _DisposeHandle,in=(ArrayHandle:l) Exit RETURN ENDP ;--------------------------------------------------------------------------- ; S_SortCompare ( CellIndex1:l,CellIndex2:l ) : bool:w ; ; This routine compares the two cells contents according to ; S_SortAscendDescendFlag for the Sort routines. S_SortCompare PROC EXPORT ;Using S_CurrentData ;Using S_SortData ;Using SANEequs input CellIndex1:l,CellIndex2:l output OneGreaterFlag:w local CellPtr1:l,CellPtr2:l local Cell1Error:w,Cell1NA:w,Cell1Value:w,Cell1Text:w local Format:w BEGIN +b stz Cell1Error stz Cell1NA stz Cell1Value stz Cell1Text lda CellIndex1+2 bmi getCell2 H_GetBlockPtr CellIndex1,CellPtr1 MoveWord [CellPtr1]:#S_CellFormat,Format bmi getCell2 and #S_CellInvalid beq cell1OK lda Format and #S_CellError beq doCell1NA inc Cell1Error bra getCell2 doCell1NA inc Cell1NA bra getCell2 cell1OK lda Format and #S_CellTypeValue bne doCell1Value inc Cell1Text bra getCell2 doCell1Value inc Cell1Value getCell2 lda CellIndex2+2 jmi doTwoGreater H_GetBlockPtr CellIndex2,CellPtr2 MoveWord [CellPtr2]:#S_CellFormat,Format bmi doTwoGreater and #S_CellInvalid beq cell2OK lda Format and #S_CellError beq doCell2NA lda #0 bra doCell2Error cell2OK lda Format and #S_CellTypeValue bne chkCell2Value lda Cell1Text beq doCell2Text bra doTextCmp chkCell2Value lda Cell1Value beq doCell2Value AddLong CellPtr1,#S_CellValue,s AddLong CellPtr2,#S_CellValue,s lda S_SortAscendDescendFlag beq cmpValueAscend bra cmpValueDescend doCell2Error ora Cell1Error doCell2NA ora Cell1NA doCell2Value ora Cell1Value doCell2Text ora Cell1Text bne doTwoGreater doOneGreater MoveWord #1,OneGreaterFlag bra Exit doTwoGreater stz OneGreaterFlag Exit RETURN cmpValueAscend Tool FCPXX,in=(:l,:l) FBGT doOneGreater bra doTwoGreater cmpValueDescend Tool FCPXX,in=(:l,:l) FBLT doOneGreater bra doTwoGreater doTextCmp SpaceWord H_GetBlockPtr [CellPtr1]:#S_CellValue,s H_GetBlockPtr [CellPtr2]:#S_CellValue,s Call D_CmpStrings,in=(:l,:l,#0:w) ; out=(:w) lda S_SortAscendDescendFlag beq cmpTextAscend cmpTextDescend pla bmi doOneGreater bra doTwoGreater cmpTextAscend pla bmi doTwoGreater beq doTwoGreater brl doOneGreater ENDP ;--------------------------------------------------------------------------- ; S_SwapColumns (TLCell:l,BRCell:l) ; ; This routine traverses the first and last column of this given region ; and calls S_SwapCell if either of the two cells in a row is non-empty. S_SwapColumns PROC EXPORT ;Using S_CurrentData ;Using S_MoveData input Col1:w,FRow:w,Col2:w,LRow:w local RowBlock:l,RowHandle:l,RowPtr:l local RowBlockPtr:l,RowOffset:w local Col1Flag:l,Col2Flag:l local MinCol:w,MaxCol:w,MaxRow:w error ErrorFlag BEGIN stz ErrorFlag stz S_DeltaMove SubWord Col2,Col1,S_DeltaMove+2 bra startRow ; For each row in the range, .... ; nextRow inc FRow startRow MoveLong S_CurRowBlock,RowBlock ora RowBlock jeq Exit MoveLong [RowBlock],RowBlockPtr MoveWord [RowBlockPtr]:#S_KeyMax,MaxRow CmpWord FRow,[RowBlockPtr]:#S_KeyMin blt tooSmall cmp MaxRow blt okRow brl Exit tooSmall lda [RowBlockPtr],y dec a sta FRow MoveWord #S_KeyArray-4,RowOffset bra searchRow okRow SubWord a,[RowBlockPtr]:y,a asl a asl a AddWord a,#S_KeyArray,RowOffset searchLoop MoveLong [RowBlockPtr]:RowOffset,RowHandle ora RowHandle bne gotRow searchRow inc FRow AddWord RowOffset,#4,RowOffset CmpWord FRow,MaxRow bge rowQuit CmpWord LRow,FRow bge searchLoop rowQuit brl Exit gotRow MoveLong [RowHandle],RowPtr MoveWord [RowPtr]:#S_KeyMax,MaxCol MoveWord [RowPtr]:#S_KeyMin,MinCol CmpWord Col1,MinCol blt noCol1 cmp MaxCol bge noCol1 CmpWord Col2,MinCol blt noCol2 cmp MaxCol blt okCols ; No Col2, but Col1 is in structure ; noCol2 stz Col2Flag bra getCol1 noCol1 CmpWord Col2,MinCol blt gotoEnd cmp MaxCol blt zeroCol1 gotoEnd brl cmpRow zeroCol1 stz Col1Flag bra getCol2 okCols SubWord a,MinCol,a asl a asl a AddWord a,#S_KeyArray,y lda [RowPtr],y iny iny ora [RowPtr],y sta Col2Flag getCol1 SubWord Col1,MinCol,a asl a asl a AddWord a,#S_KeyArray,y lda [RowPtr],y iny iny ora [RowPtr],y sta Col1Flag bra chkCols getCol2 SubWord Col2,MinCol,a asl a asl a AddWord a,#S_KeyArray,y lda [RowPtr],y iny iny ora [RowPtr],y sta Col2Flag chkCols lda Col2Flag ora Col1Flag beq cmpRow Call S_SwapCell,in=(Col1:w,FRow:w),err=ErrorFlag bcs Exit cmpRow CmpWord FRow,LRow jlt nextRow Exit RETURN ENDP ;--------------------------------------------------------------------------- ; S_SwapRows (TLCell:l,BRCell:l) ; ; This routine traverses the first and last rows of this given region ; and calls S_SwapCell if either of the two cells in a column is non-empty. S_SwapRows PROC EXPORT ;Using S_CurrentData ;Using S_MoveData input FCol:w,Row1:w,LCol:w,Row2:w local RowIndex:l,RowPtr:l,ColIndex:l local ColOffset:w,MaxCol:w local RowBlock:l,RowBlockPtr:l local NextCol1:w,NextCol2:w error ErrorFlag BEGIN stz ErrorFlag lda S_CurRowBlock ora S_CurRowBlock+2 jeq Exit SubWord Row2,Row1,S_DeltaMove stz S_DeltaMove+2 stz NextCol1 stz NextCol2 bra start ; For each cell in the row, .... ; nextCol inc FCol start CmpWord NextCol1,FCol blt getCol1 jeq makeCall2 brl gotNextCol1 getCol1 MoveLong S_CurRowBlock,RowBlock MoveLong [RowBlock],RowBlockPtr CmpWord Row1,[RowBlockPtr]:#S_KeyMax bge noRow1 SubWord a,[RowBlockPtr]:#S_KeyMin,a bge row1InRange noRow1 brl noMoreRow1 row1InRange asl a asl a AddWord a,#S_KeyArray,y MoveLong [RowBlockPtr]:y,RowIndex ora RowIndex beq noRow1 ; Find first used Col Greater/Equal to FCol ; MoveLong [RowIndex],RowPtr MoveWord [RowPtr]:#S_KeyMax,MaxCol CmpWord FCol,MaxCol bge noRow1 sta NextCol1 SubWord a,[RowPtr]:#S_KeyMin,a bge col1InRange ; Try Mincol as NextCol1 ; lda [RowPtr],y dec a sta nextCol1 MoveWord #S_KeyArray-4,ColOffset bra startCol1Loop col1InRange asl a asl a AddWord a,#S_KeyArray,ColOffset tay MoveLong [RowPtr]:y,ColIndex ora ColIndex beq startCol1Loop brl makeCall2 findCol1Loop MoveLong [RowPtr]:ColOffset,ColIndex ora ColIndex bne gotNextCol1 startCol1Loop inc NextCol1 AddWord ColOffset,#4,ColOffset CmpWord NextCol1,MaxCol bge noMoreRow1 CmpWord LCol,NextCol1 bge findCol1Loop noMoreRow1 AddWord LCol,#1,NextCol1 gotNextCol1 CmpWord NextCol2,FCol jge chkFCol MoveLong S_CurRowBlock,RowBlock MoveLong [RowBlock],RowBlockPtr CmpWord Row2,[RowBlockPtr]:#S_KeyMax bge noRow2 SubWord a,[RowBlockPtr]:#S_KeyMin,a bge row2InRange noRow2 brl noMoreRow2 row2InRange asl a asl a AddWord a,#S_KeyArray,y MoveLong [RowBlockPtr]:y,RowIndex ora RowIndex beq noRow2 ; Find first used Col Greater/Equal to FCol ; MoveLong [RowIndex],RowPtr MoveWord [RowPtr]:#S_KeyMax,MaxCol CmpWord FCol,MaxCol bge noRow2 sta NextCol2 SubWord a,[RowPtr]:#S_KeyMin,a bge col2InRange ; Try MinCol as the next col ; lda [RowPtr],y dec a sta nextCol2 MoveWord #S_KeyArray-4,ColOffset bra startCol2Loop col2InRange asl a asl a AddWord a,#S_KeyArray,ColOffset tay MoveLong [RowPtr]:y,ColIndex ora ColIndex beq startCol2Loop bra makeCall2 findCol2Loop MoveLong [RowPtr]:ColOffset,ColIndex ora ColIndex bne chkFCol startCol2Loop inc NextCol2 AddWord ColOffset,#4,ColOffset CmpWord NextCol2,MaxCol bge noMoreRow2 CmpWord LCol,NextCol2 bge findCol2Loop noMoreRow2 AddWord LCol,#1,NextCol2 chkFCol CmpWord NextCol1,NextCol2 bge chkRow2 cmp LCol beq makeCall1 blt makeCall1 bra Exit chkRow2 CmpWord NextCol2,LCol beq makeCall1 bge Exit makeCall1 sta FCol makeCall2 Call S_SwapCell,in=(FCol:w,Row1:w),err=ErrorFlag bcs Exit CmpWord FCol,LCol bge Exit brl nextCol Exit RETURN ENDP END