-- ROMMakerCommon.mesa
-- cell subroutines to run within Chipmonk
-- last modified by E. McCreight, February 2, 1982 6:46 PM
-- written by E. McCreight, August 7, 1981 3:52 PM
DIRECTORY
ChipUserInt,
InlineDefs,
ppdddefs,
ppddefs,
ppdefs,
RomMakerDefs,
StringDefs;
RomMakerCommon: PROGRAM
IMPORTS ChipUserInt, InlineDefs,
ppdddefs, ppddefs, ppdefs, StringDefs
EXPORTS RomMakerDefs =
PUBLIC BEGIN OPEN ChipUserInt, ppdddefs, ppddefs,
ppdefs, RomMakerDefs;
lpp: listPtr ← NIL;
dirFactor: ARRAY Direction OF Point ←
[ -- vertical -- [x: 0, y: 1],
-- horizontal -- [x: 1, y: 0],
-- diagonal -- [x: 1, y: 1],
-- up -- [x: 0, y: -1],
-- down -- [x: 0, y: 1],
-- left -- [x: -1, y: 0],
-- right -- [x: 1, y: 0],
-- upAndLeft -- [x: -1, y: -1],
-- upAndRight -- [x: 1, y: -1],
-- downAndLeft -- [x: -1, y: 1],
-- downAndRight -- [x: 1, y: 1]];
FindCell: PROCEDURE [
cellFamily: STRING, member: STRING, required: BOOLEAN ← FALSE,
vCompat: Cell ← NIL, hCompat: Cell ← NIL] RETURNS [Cell] =
BEGIN OPEN StringDefs;
s: STRING ← [100];
s.length ← 0;
AppendString[to: s, from: cellFamily];
AppendString[to: s, from: member];
FOR cp: LONG POINTER TO cList ← cellList, cp.nxt WHILE cp # NIL DO
IF StringDefs.EquivalentString[cp.name, s] THEN
BEGIN
c: Cell ← cp.ob;
IF vCompat # NIL THEN CheckPitchCompatability[c, vCompat, vertical];
IF hCompat # NIL THEN CheckPitchCompatability[c, hCompat, horizontal];
RETURN[c];
END;
ENDLOOP;
IF required THEN
{Explain["Missing cell in family [Confirm]"L, s]; SIGNAL Punt};
RETURN[NIL];
END;
FindDCell: PROCEDURE [
cellFamily, memberPrefix: STRING, required: BOOLEAN ← FALSE,
vCompat: Cell ← NIL, hCompat: Cell ← NIL] RETURNS [d: DCell] =
BEGIN OPEN StringDefs;
originalLength: INTEGER ← memberPrefix.length;
member: STRING ← [50];
member.length ← 0;
AppendString[to: member, from: memberPrefix];
AppendString[to: member, from: "0"L];
d[FALSE] ← FindCell[cellFamily, member, FALSE, vCompat, hCompat];
member.length ← originalLength;
AppendString[to: member, from: "1"L];
d[TRUE] ← FindCell[cellFamily, member, FALSE, vCompat, hCompat];
IF d[FALSE]=NIL THEN
d[FALSE] ← FindCell[cellFamily, memberPrefix, required,
vCompat, hCompat];
IF d[TRUE]=NIL THEN d[TRUE] ← d[FALSE];
CheckPitchCompatability[d[FALSE], d[TRUE], diagonal];
END; -- of FindDCell
FindDCellPr: PROCEDURE [
cellFamily, memberPrefix: STRING, required: BOOLEAN ← FALSE,
vCompat: Cell ← NIL, hCompat: Cell ← NIL] RETURNS [p: DCellPr] =
BEGIN OPEN StringDefs;
originalLength: INTEGER ← memberPrefix.length;
member: STRING ← [50];
member.length ← 0;
AppendString[to: member, from: memberPrefix];
AppendString[to: member, from: "0"L];
p[FALSE] ← FindDCell[cellFamily, member, required, vCompat, hCompat];
member.length ← originalLength;
AppendString[to: member, from: "1"L];
p[TRUE] ← FindDCell[cellFamily, member, required, vCompat, hCompat];
CheckPitchCompatability[p[FALSE][FALSE], p[TRUE][FALSE], diagonal];
END; -- of FindDCell
CheckPitchCompatability: PROCEDURE [
c1, c2: Cell, dir: Direction, rep1: Point ← [1, 1], rep2: Point ← [1, 1]] =
BEGIN OPEN StringDefs;
FindCellName: PROCEDURE [c: Cell] RETURNS [STRING] =
BEGIN
FOR cp: LONG POINTER TO cList ← cellList, cp.nxt WHILE cp # NIL DO
IF c = cp.ob THEN RETURN[cp.name] ENDLOOP;
RETURN[""];
END;
IF c1#NIL AND c2#NIL AND Offset[, c1, dir, rep1]#Offset[, c2, dir, rep2] THEN
BEGIN
cellNames: STRING ← [50];
cellNames.length ← 0;
AppendString[to: cellNames, from: FindCellName[c1]];
AppendString[to: cellNames, from: " - "L];
AppendString[to: cellNames, from: FindCellName[c2]];
SELECT dir FROM
vertical, up, down =>
Explain["Incompatible cell vertical pitches [Confirm]"L, cellNames];
horizontal, left, right =>
Explain["Incompatible cell horizontal pitches [Confirm]"L, cellNames];
ENDCASE => Explain["Incompatible cell sizes [Confirm]"L, cellNames];
SIGNAL Punt;
END;
END; -- of CheckPitchCompatability
Repeat: PROCEDURE[p: Point, cell: Cell, corner: Direction ← topLeft,
dir: Direction ← horizontal, rep: locNum ← 1,
midCell: Cell ← NIL, midGap: locNum ← 0,
altCell: Cell ← NIL, altMod: INTEGER ← 0,
name, midName: NameGroup ← nilNameGroup] =
BEGIN
GetCell: PROCEDURE[i: INTEGER] RETURNS[Cell] =
{RETURN[
IF i>0 AND altCell#NIL AND altMod>0 AND (i MOD altMod)#0 THEN altCell
ELSE cell]};
RepeatArbitrary[p: p, cp: GetCell, corner: corner, dir: dir,
rep: rep, midCell: midCell, midGap: midGap,
name: name, midName: midName];
END;
RepeatArbitrary: PROCEDURE[p: Point, cp: PROCEDURE[i: INTEGER] RETURNS[Cell],
corner: Direction ← topLeft, dir: Direction ← upAndLeft,
rep: INTEGER ← 1, midCell: Cell ← NIL, midGap: locNum ← 0,
name, midName: NameGroup ← nilNameGroup] =
BEGIN
cellSize: Point ← CellSize[cp[0]];
midCellSize: Point ← CellSize[midCell];
SELECT corner FROM
topRight => p.x ← p.x-cellSize.x;
bottomLeft => p.y ← p.y-cellSize.y;
bottomRight => p ← [x: p.x-cellSize.x, y: p.y-cellSize.y];
ENDCASE => NULL;
SELECT dir FROM
vertical, up, down =>
BEGIN
FOR iy: INTEGER IN [0..rep) DO
PlaceCell[p: p, cell: cp[iy],
rep: [0, iy], midCellSize: midCellSize,
midGap: [0, midGap], name: name];
ENDLOOP;
FOR iy: INTEGER IN [0..MidCellRep[midGap, rep-1, cellSize.y]) DO
PlaceCell[p: [p.x,
p.y+(iy+1)*cellSize.y*CellsPerGap[midGap, cellSize.y]+iy*midCellSize.y],
cell: midCell, name: midName];
ENDLOOP;
END;
horizontal, left, right =>
BEGIN
FOR ix: INTEGER IN [0..rep) DO
PlaceCell[p: p, cell: cp[ix],
rep: [ix, 0], midCellSize: midCellSize,
midGap: [midGap, 0], name: name];
ENDLOOP;
FOR ix: INTEGER IN [0..MidCellRep[midGap, rep-1, cellSize.x]) DO
PlaceCell[
p: [p.x+(ix+1)*cellSize.x*CellsPerGap[midGap, cellSize.x]+ix*midCellSize.x,
p.y],
cell: midCell, name: midName];
ENDLOOP;
END;
ENDCASE => NULL;
END; -- of RepeatArbitrary
CellsPerGap: PROCEDURE[gap, sizePerCell: locNum] RETURNS[INTEGER] =
{RETURN[(gap+sizePerCell-1)/sizePerCell] -- ceiling --};
MidCellRep: PROCEDURE[gap, nCells, sizePerCell: locNum] RETURNS[INTEGER] =
BEGIN
cellsPerGap: INTEGER ← CellsPerGap[gap, sizePerCell];
RETURN[IF cellsPerGap=0 THEN 0 ELSE nCells/cellsPerGap];
END;
MakeMidGrid: PROCEDURE[p: Point, cell: Cell, rep: Point,
midVCell, midHCell, midVHCell: Cell ← NIL, midGap: Point ← [0,0]] =
BEGIN
cellSize: Point ← CellSize[cell];
midCellSize: Point ← [x: CellSize[midVCell].x,
y: CellSize[midHCell].y];
sizePerGap: Point ← [x: cellSize.x*CellsPerGap[midGap.x, cellSize.x],
y: cellSize.y*CellsPerGap[midGap.y, cellSize.y]];
midCellRep: Point ← [x: MidCellRep[midGap.x, rep.x-1, cellSize.x],
y: MidCellRep[midGap.y, rep.y-1, cellSize.y]];
FOR ix: INTEGER IN [0..rep.x) DO
FOR iy: INTEGER IN [0..midCellRep.y) DO
PlaceCell[p: [p.x, p.y+sizePerGap.y+iy*(sizePerGap.y+midCellSize.y)], cell: midHCell,
rep: [ix, 0], midCellSize: CellSize[midVHCell], midGap: midGap];
ENDLOOP;
ENDLOOP;
FOR ix: INTEGER IN [0..midCellRep.x) DO
Repeat[p: [p.x+sizePerGap.x+ix*(sizePerGap.x+midCellSize.x), p.y], cell: midVCell,
dir: vertical, rep: rep.y, midCell: midVHCell, midGap: midGap.y];
ENDLOOP;
END; -- of MakeMidGrid
PlaceCell: PROCEDURE[p: Point, cell: Cell, rep: Point ← [0,0], midCellSize: Point ← [0,0],
midGap: Point ← [0,0], name: NameGroup ← nilNameGroup] =
BEGIN
IF cell#NIL THEN
BEGIN
cp: Point ← Offset[p: p, cell: cell, dir: diagonal, rep: rep,
midCellSize: midCellSize, midGap: midGap];
lp: listPtr ← makeList[cell, cp.x, cp.y, 0, 0];
AddInstName[lp, name, rep];
lpp ← insertList[lpp, lp];
END;
END;
AddInstName: PROCEDURE[lp: listPtr, name: NameGroup,
rep: Point] =
BEGIN OPEN StringDefs;
ComputeIndex: PROCEDURE[i: INTEGER, coef: Point]
RETURNS[indx: INTEGER] =
BEGIN
k: INTEGER ← coef.x*i+coef.y;
RETURN[IF k<0 THEN 0 ELSE k];
END;
s: STRING ← [100];
tp: LONG POINTER TO text prop ← NIL;
xIndx: INTEGER ← ComputeIndex[rep.x, name.x];
yIndx: INTEGER ← ComputeIndex[rep.y, name.y];
IF lp=NIL OR name.basicName=NIL THEN RETURN;
s.length ← 0;
AppendString[to: s, from: name.basicName];
IF xIndx#0 OR yIndx#0 THEN AppendChar[s: s, c: '-];
IF xIndx#0 THEN AppendDecimal[s: s, n: xIndx];
IF yIndx#0 THEN
BEGIN
AppendChar[s: s, c: '-];
AppendDecimal[s: s, n: yIndx];
END;
tp ← GetSpace[SIZE[text prop]];
tp↑ ← [nxt: lp.props, varpart: text[s: newString[s]]];
lp.props ← tp;
END; -- of AddInstName
DirSize: PROCEDURE[size: Point, dir: Direction ← diagonal] RETURNS[Point] =
{RETURN[
[x: dirFactor[dir].x*size.x, y: dirFactor[dir].y*size.y]]};
CellSize: PROCEDURE[cell: Cell, dir: Direction ← diagonal] RETURNS[Point] =
{RETURN[IF cell=NIL THEN [0,0] ELSE
DirSize[size: [x: cell.size[0], y: cell.size[1]], dir: dir]]};
Offset: PROCEDURE[p: Point ← [0, 0], cell: Cell, dir: Direction, rep: Point ← [0, 0],
midCell: Cell ← NIL, midCellSize: Point ← [0,0],
midGap: Point ← [0, 0], includeTerminalMid: BOOLEAN ← TRUE]
RETURNS [Point] =
BEGIN
midRep: Point ← IF includeTerminalMid THEN rep ELSE
[x: rep.x-1, y: rep.y-1];
midCellSize ← IF midCell#NIL THEN CellSize[midCell, dir]
ELSE DirSize[midCellSize, dir];
RETURN[IF cell=NIL THEN p ELSE
[x: p.x+rep.x*CellSize[cell, dir].x+
MidCellRep[midGap.x, midRep.x, CellSize[cell].x]*
midCellSize.x,
y: p.y+rep.y*CellSize[cell, dir].y+
MidCellRep[midGap.y, midRep.y, CellSize[cell].y]*
midCellSize.y]];
END;
BlockSize: PROCEDURE [cell: Cell, rep: Point ← [1, 1],
midCell: Cell ← NIL, midGap: Point ← [0, 0]]
RETURNS [Point] =
{RETURN[Offset[cell: cell, rep: rep, midCell: midCell, midGap: midGap,
p: [0,0], dir: diagonal, includeTerminalMid: FALSE]]};
MakeNewCell: PROCEDURE [name: STRING, lpp: listPtr]
RETURNS [cp: LONG POINTER TO cList] =
BEGIN
min: Point ← [LAST[locNum], LAST[locNum]];
max: Point ← [FIRST[locNum], FIRST[locNum]];
lp: listPtr;
FOR lp ← lpp, lp.nxt WHILE lp # NIL DO
ii: [0..1] ← IF InlineDefs.BITAND[lp.idx, 4] = 0 THEN 0 ELSE 1;
min ← [MIN[min.x, lp.lx], MIN[min.y, lp.ly]];
max ← [
MAX[max.x, lp.lx + lp.ob.size[ii]], MAX[
max.y, lp.ly + lp.ob.size[ii + 1]]];
ENDLOOP;
FOR lp ← lpp, lp.nxt WHILE lp # NIL DO
lp.lx ← lp.lx - min.x; lp.ly ← lp.ly - min.y; lp.selected ← FALSE; ENDLOOP;
cp ← alocCList[];
cp.nxt ← cellList;
cellList ← cp;
cp.ob ← makeCell[max.x - min.x, max.y - min.y, 0, lpp];
cp.name ← name;
END; -- of MakeNewCell
AddToMasterList: PROCEDURE[lpp: listPtr] =
BEGIN
min: Point ← [LAST[locNum], LAST[locNum]];
max: Point ← [FIRST[locNum], FIRST[locNum]];
lp: listPtr;
FOR lp ← lpp, lp.nxt WHILE lp # NIL DO
ii: [0..1] ← IF InlineDefs.BITAND[lp.idx, 4] = 0 THEN 0 ELSE 1;
min ← [MIN[min.x, lp.lx], MIN[min.y, lp.ly]];
max ← [
MAX[max.x, lp.lx + lp.ob.size[ii]], MAX[
max.y, lp.ly + lp.ob.size[ii + 1]]];
ENDLOOP;
FOR lp ← masterList, lp.nxt WHILE lp # NIL DO
IF lp.selected THEN
BEGIN
lp.selected ← FALSE;
reDrawRect[getRect[lp], 0, TRUE, TRUE, FALSE];
END;
ENDLOOP;
FOR lp ← lpp, lp WHILE lp # NIL DO
p: listPtr ← lp; lp ← p.nxt; p.nxt ← NIL;
p.lx ← p.lx - min.x + xx;
p.ly ← p.ly - min.y + yy;
p.selected ← TRUE;
masterList ← insertList[masterList, p];
ENDLOOP;
putMark[xx, yy];
reDrawRect[
[x1: xx, x2: xx+max.x-min.x, y1: yy, y2: yy+max.y-min.y],
0, TRUE, TRUE, FALSE];
anyChanges ← sinceIOchanges ← TRUE;
END; -- of AddToMasterList
DrawCell: PROCEDURE [obp: Cell] =
BEGIN
lp: listPtr ← makeList[obp.p.anotherme[obp], xx, yy, 0, 0];
obp.returnable ← FALSE;
masterList ← insertList[masterList, lp];
selNewThing[masterList, lp, TRUE];
putMark[xx, yy];
reDrawRect[getRect[lp], 0, TRUE, TRUE, FALSE];
anyChanges ← sinceIOchanges ← TRUE;
END; -- of DrawCell
END. -- of RomMakerCommon