-- ppSortLists.mesa -- A Chipmonk package that sorts Chipmonk object -- lists in increasing order by smallest x, and within equal -- smallest x in increasing order by smallest y. -- written by E. McCreight, October 13, 1981 3:15 PM DIRECTORY ppdefs, SegmentDefs, ZoneAllocDefs; ppSortLists: PROGRAM IMPORTS ppdefs, SegmentDefs, ZoneAllocDefs = BEGIN OPEN ppdefs; ListPtr: TYPE = LONG POINTER TO list ← NIL; SortChipmonkWorld: PUBLIC PROCEDURE[] = BEGIN FOR cp: LONG POINTER TO cell object ← GetCellSuper[], cp.super WHILE cp#NIL DO cp.marked ← FALSE; ENDLOOP; SortObjectListAndItsCells[@masterList]; END; -- of SortChipmonkWorld SortObjectListAndItsCells: PUBLIC PROCEDURE[p: LONG POINTER TO ListPtr] = BEGIN SortObjectList[p]; FOR lp: ListPtr ← p↑, lp.nxt WHILE lp#NIL DO WITH obj: lp.ob SELECT FROM cell => IF NOT obj.marked THEN BEGIN obj.marked ← TRUE; -- stops infinite regress SortObjectListAndItsCells[@obj.ptr]; END; ENDCASE => NULL; ENDLOOP; END; -- of SortObjectListAndItsCells SortObjectList: PUBLIC PROCEDURE[p: LONG POINTER TO ListPtr] = BEGIN Heap: TYPE = RECORD[ item: SEQUENCE max: CARDINAL OF ListPtr]; h: LONG POINTER TO Heap ← NIL; l: CARDINAL; r: CARDINAL ← 0; lp, last: ListPtr; stillInOrder: BOOLEAN ← TRUE; FOR lp ← p↑, lp.nxt WHILE lp#NIL DO r ← r+1; IF stillInOrder AND lp.nxt#NIL AND (lp.lx>lp.nxt.lx OR (lp.lx=lp.nxt.lx AND lp.ly>lp.nxt.ly)) THEN stillInOrder ← FALSE; ENDLOOP; IF stillInOrder THEN RETURN; h ← ZoneAllocDefs.uz.NEW[Heap[r+1] ! SegmentDefs.InsufficientVM => GOTO Cant]; l ← 1; FOR lp ← p↑, lp.nxt WHILE lp#NIL DO h.item[l] ← lp; l ← l+1; ENDLOOP; -- Sort by increasing lx, and within equal lx by increasing ly. -- At this point, r>=2. last ← NIL; l ← r/2+1; WHILE r>1 DO i, j: CARDINAL; item: ListPtr; kItem: locNum; IF l>1 THEN {l ← l-1; item ← h.item[l]} ELSE BEGIN item ← h.item[r]; h.item[1].nxt ← last; last ← h.item[1]; r ← r-1; END; kItem ← item.lx; FOR i ← l, j DO dx: locNum; j ← i+i; -- I'd like to say 2*i but I don't trust the optimizer IF j>r THEN EXIT; IF j<r THEN BEGIN dx ← h.item[j].lx-h.item[j+1].lx; IF dx<0 OR (dx=0 AND h.item[j].ly<h.item[j+1].ly) THEN j ← j+1; END; dx ← kItem-h.item[j].lx; IF dx<0 OR (dx=0 AND item.ly<h.item[j].ly) THEN h.item[i] ← h.item[j] ELSE EXIT; ENDLOOP; h.item[i] ← item; ENDLOOP; h.item[1].nxt ← last; p↑ ← h.item[1]; ZoneAllocDefs.uz.FREE[@h]; EXITS Cant => NULL; -- for now END; -- of SortObjectList SortChipmonkWorld[]; -- the main program! END. -- of ppSortLists