-- second procedure exporting module of silicon (pretty picture) program
-- last modified by McCreight, December 21, 1983 10:02 AM
-- to copy text properties properly
-- modified (slightly) by Petit September 23, 1981 8:32 PM
DIRECTORY
ChipUserInt,
multiGraphicsDefs,
InlineDefs,
SegmentDefs,
StringDefs,
ppdddefs,ppddefs,
ppdefs;
ppprocs2: PROGRAM
IMPORTS ChipUserInt, ppdddefs,ppdefs, ppddefs,
multiGraphicsDefs, InlineDefs, StringDefs
EXPORTS ppdefs, ppddefs,ppdddefs =
BEGIN
OPEN ppdefs, ppdddefs,ppddefs, multiGraphicsDefs, SegmentDefs, StringDefs, InlineDefs;
masterList: PUBLIC LONG POINTER TO list;
cellList: PUBLIC LONG POINTER TO cList;
cellNameMode: PUBLIC BOOLEAN ← FALSE;
cnList: PUBLIC LONG POINTER TO list ← NIL;
xx, yy: PUBLIC INTEGER;
bb: PUBLIC BOOLEAN;
ii, jj: CARDINAL;
lp, lqp: LONG POINTER TO list;
cp: LONG POINTER TO cList;
localNameString:STRING←[30];
localBusString:STRING←[30];
ke: keyEvent;
ss: STRING;
cellStack: PUBLIC LONG POINTER TO cellSE;
unDelPnt: PUBLIC LONG POINTER TO list;
unDelGrpCnt, unDelItemCnt: PUBLIC CARDINAL;
maxZeeLevels: CARDINAL ← 8;
yWdt: CARDINAL = 13;
sss: STRING ← [100];
tiCx: CARDINAL = 100;
doZee: PUBLIC cmdProc =
BEGIN
x, y: INTEGER;
width: CARDINAL;
count: PROCEDURE [lev: CARDINAL, p: LONG POINTER TO cell object]
RETURNS [cnt: CARDINAL] =
BEGIN
othCnt: CARDINAL;
lp, lpp: LONG POINTER TO list;
lev ← lev + 1;
cnt ← 0;
othCnt ← 0;
lp ← p.ptr;
WHILE lp # NIL DO lp.mark ← 0; lp ← lp.nxt; ENDLOOP;
lp ← p.ptr;
WHILE lp # NIL DO
IF lp.ob.otyp = cell AND lp.mark = 0 THEN
BEGIN
othCnt ← othCnt + count[lev, LOOPHOLE[lp.ob]];
cnt ← cnt + 1;
lpp ← lp.nxt;
WHILE lpp # NIL DO
IF lp.ob = lpp.ob THEN lpp.mark ← 1; lpp ← lpp.nxt; ENDLOOP;
END;
lp ← lp.nxt;
ENDLOOP;
lp ← p.ptr;
WHILE lp # NIL DO lp.mark ← 0; lp ← lp.nxt; ENDLOOP;
cnt ← MAX[cnt, othCnt];
cnt ← MAX[cnt, 1];
END;
drCll: PROCEDURE [
lev: CARDINAL, p: LONG POINTER TO cell object, x, y: INTEGER,
wd, inCnt: CARDINAL] =
BEGIN
lp, lpp: LONG POINTER TO list;
cp: LONG POINTER TO cList;
nxtx: INTEGER;
twd, tt: CARDINAL;
s: STRING;
lev ← lev + 1;
[s, cp] ← cellNam[p, inCnt];
nxtx ← MeasureText[s, fnt];
lpp ← makeList[
makeCnText[s, nxtx, yWdt, wd, p, cp], x, y + wd*yWdt/2, 0, 0];
lpp.nxt ← cnList;
cnList ← lpp;
nxtx ← nxtx + x + 5;
lp ← p.ptr;
WHILE lp # NIL DO
IF lp.ob.otyp = cell AND lp.mark = 0 THEN
BEGIN
lpp ← lp;
tt ← 0;
WHILE lpp # NIL DO
IF lp.ob = lpp.ob THEN BEGIN tt ← tt + 1; lpp.mark ← 1; END;
lpp ← lpp.nxt;
ENDLOOP;
twd ← count[lev, LOOPHOLE[lp.ob]];
drCll[lev, LOOPHOLE[lp.ob], nxtx, y, twd, tt];
y ← y + twd*yWdt;
END;
lp ← lp.nxt;
ENDLOOP;
END;
cnList ← NIL;
cellNameMode ← TRUE;
y ← 40;
x ← 20;
cp ← cellList;
WHILE cp # NIL DO
width ← count[0, LOOPHOLE[cp.ob]];
drCll[0, LOOPHOLE[cp.ob], x, y, width, 1];
y ← y + width*yWdt + 5;
cp ← cp.nxt;
ENDLOOP;
dChange ← FALSE;
reDrawRect[[0, 0, 0, 0], 2, TRUE, FALSE, TRUE];
END;
cellNam: PROCEDURE [p: LONG POINTER TO cell object, cnt: CARDINAL]
RETURNS [STRING, LONG POINTER TO cList] =
BEGIN
cpp: LONG POINTER TO cList ← cellList;
lp: LONG POINTER TO list ← p.ptr;
i: INTEGER ← 0;
flg: BOOLEAN ← FALSE;
sss.length ← 0;
IF cnt > 1 THEN BEGIN AppendDecimal[sss, cnt]; AppendChar[sss, 'x]; END;
WHILE cpp # NIL DO
IF p = cpp.ob THEN BEGIN AppendString[sss, cpp.name]; flg ← TRUE; EXIT; END;
cpp ← cpp.nxt;
ENDLOOP;
IF NOT flg THEN AppendString[sss, "--noname--"];
AppendChar[sss, '{];
WHILE lp # NIL DO i ← i + 1; lp ← lp.nxt; ENDLOOP;
AppendDecimal[sss, i];
AppendChar[sss, '}];
RETURN[sss, cpp];
END;
delCellDef: PUBLIC PROCEDURE [
cn: LONG POINTER TO cList, ob: LONG POINTER TO cell object] =
BEGIN
sp: LONG POINTER TO list;
lpp: LONG POINTER TO list;
defobs: LONG POINTER TO list ← ob.ptr;
scp, tcp: LONG POINTER TO cell object;
scp ← GetCellSuper[];
sp ← GetSuperPointer[];
lp ← sp;
ob.returnable ← TRUE;
WHILE lp # NIL DO
IF lp.ob = ob THEN
BEGIN
lpp ← sp;
IF masterList = lp THEN masterList ← lp.nxt
ELSE
WHILE lpp # NIL DO
IF lpp.nxt = lp THEN BEGIN lpp.nxt ← lp.nxt; EXIT; END;
lpp ← lpp.super;
ENDLOOP;
tcp ← scp;
WHILE tcp # NIL DO
IF tcp.ptr = lp THEN BEGIN tcp.ptr ← lp.nxt; EXIT; END;
tcp ← tcp.super;
ENDLOOP;
lp.nxt ← NIL;
lpp ← lp.super;
flushDel[lp];
lp ← lpp;
END
ELSE lp ← lp.super;
ENDLOOP;
IF cn # NIL THEN
BEGIN
IF cellList = cn THEN cellList ← cellList.nxt
ELSE
BEGIN
cp ← cellList;
WHILE cp # NIL DO
IF cp.nxt = cn THEN BEGIN cp.nxt ← cn.nxt; EXIT; END;
cp ← cp.nxt;
ENDLOOP;
END;
cn.ob.p.release[cn.ob];
END;
END;
moveOb: PUBLIC PROCEDURE [p: LONG POINTER TO list, x, y: INTEGER] =
BEGIN
reDrawRect[getRect[p], 3, TRUE, TRUE, FALSE];
p.lx ← p.lx + x;
p.ly ← p.ly + y;
reDrawRect[getRect[p], 0, TRUE, TRUE, FALSE];
END;
doHard: PUBLIC cmdProc =
BEGIN
ss: STRING;
ke: keyEvent;
ok: BOOLEAN;
[ok, ss, ke] ← typeIn[
"Type File Name", "without extension", "I will add .press"];
refreshTypeInScreen[];
IF NOT ok THEN RETURN;
hardOut[ss, masterList];
END;
doExpS: PUBLIC cmdProc =
BEGIN
backPnt: LONG POINTER TO LONG POINTER TO list;
lp ← masterList;
backPnt ← @masterList;
WHILE lp # NIL DO
IF lp.selected AND (lp.ob.otyp = cell OR lp.ob.otyp=bus) THEN
BEGIN
backPnt↑ ← lp.nxt;
anyChanges ← sinceIOchanges ← TRUE;
doTheExp[lp];
RETURN;
END;
backPnt ← @lp.nxt;
lp ← lp.nxt;
ENDLOOP;
END;
doExpP: PUBLIC cmdProc =
BEGIN
backPnt: LONG POINTER TO LONG POINTER TO list;
lp ← masterList;
backPnt ← @masterList;
WHILE lp # NIL DO
IF (lp.ob.otyp = cell OR lp.ob.otyp=bus) AND lp.ob.p.inMe[lp.ob, xx - lp.lx, yy - lp.ly, lp.idx]
THEN
BEGIN
anyChanges ← sinceIOchanges ← TRUE;
backPnt↑ ← lp.nxt;
doTheExp[lp];
RETURN;
END;
backPnt ← @lp.nxt;
lp ← lp.nxt;
ENDLOOP;
END;
doTheExp: PROCEDURE [lpp: LONG POINTER TO list] =
BEGIN
dp: LONG POINTER TO cell object;
bb: LONG POINTER TO bus object;
lz: LONG POINTER TO list;
id: CARDINAL ← lpp.idx;
xo: CARDINAL ← BITAND[id, 1];
-- IF xo#0 THEN id←id+8;
id ← BITAND[id, 12];
IF lpp # NIL THEN
BEGIN
IF lpp.ob.otyp=bus THEN
BEGIN
x,y,len:INTEGER;
bb←LOOPHOLE[lpp.ob];
lz←NIL;
x←lpp.lx;
y←lpp.ly+bb.offsetFirst;
len←bb.firstLength;
THROUGH [0..bb.wCnt) DO
lqp←makeList[makeWire[len,bb.wwidth,bb.l],x,y,0,0];
lqp.nxt←lz;lz←lqp;
x←x+bb.wspace;
y←y+bb.topIncr;
len←len+bb.lenIncr;
ENDLOOP;
END
ELSE IF lpp.ob.otyp=cell THEN
BEGIN
dp ← LOOPHOLE[lpp.ob];
lqp ← dp.ptr;
lz ← NIL;
WHILE lqp # NIL DO
lz ← copyObject[lp: lqp, mp: lz, xoff: lpp.lx, yoff: lpp.ly];
lqp ← lqp.nxt;
ENDLOOP;
END;
WHILE id # 0 DO rotReflList[FALSE, lz, TRUE]; id ← id - 4; ENDLOOP;
IF xo # 0 THEN rotReflList[TRUE, lz, TRUE];
lqp ← lz;
WHILE lqp # NIL AND lqp.nxt # NIL DO lqp ← lqp.nxt; ENDLOOP;
IF lqp # NIL THEN BEGIN lqp.nxt ← masterList; masterList ← lz; END;
lpp.nxt ← NIL;
-- this is a storage leak, but the screen updaters may
-- be holding a pointer to this list, for drawing a selection box.
-- flushDel[lpp];
dChange ← TRUE;
END;
reCount[];
END;
reCount: PUBLIC PROCEDURE =
BEGIN
selCount ← 0;
lp ← masterList;
WHILE lp # NIL DO
IF lp.selected THEN selCount ← selCount + 1; lp ← lp.nxt; ENDLOOP;
END;
undrawUnsel: PROCEDURE [mp: LONG POINTER TO list] =
BEGIN
r: Rect;
selCount ← 0;
lp ← mp;
ii ← 1;
jj ← 1;
WHILE lp # NIL DO
IF lp.selected THEN
BEGIN
lp.selected ← FALSE;
IF jj < ii THEN
BEGIN
r ← IF jj = 1 THEN getRect[lp] ELSE mergeRects[r, getRect[lp]];
jj ← jj + 1;
END
ELSE
BEGIN
IF jj = 1 THEN reDrawRect[getRect[lp], 1, TRUE, TRUE, FALSE]
ELSE reDrawRect[mergeRects[r, getRect[lp]], 1, TRUE, TRUE, FALSE];
jj ← 1;
ii ← ii + 1;
END;
END;
lp ← lp.nxt;
ENDLOOP;
IF jj > 1 THEN reDrawRect[r, 1, TRUE, TRUE, FALSE];
END;
selSingle: PUBLIC PROCEDURE [mp: LONG POINTER TO list, xx, yy: INTEGER] =
BEGIN
lpp: LONG POINTER TO list ← NIL;
sflg: BOOLEAN ← FALSE;
lp ← mp;
IF lp = NIL THEN RETURN;
WHILE lp # NIL DO
IF lp.ob.p.inMe[lp.ob, xx - lp.lx, yy - lp.ly, lp.idx] THEN
BEGIN
IF lpp = NIL THEN lpp ← lp;
IF sflg THEN BEGIN lpp ← lp; EXIT; END;
IF lp.selected THEN sflg ← TRUE;
END;
lp ← lp.nxt;
ENDLOOP;
undrawUnsel[mp];
IF lpp = NIL THEN RETURN;
lpp.selected ← TRUE;
selCount ← 1;
setupSelDisplay[lpp];
drawNewlySel[lpp];
END;
selExtend: PUBLIC PROCEDURE [mp: LONG POINTER TO list, xx, yy: INTEGER] =
BEGIN
lp ← mp;
WHILE lp # NIL DO
IF NOT lp.selected AND lp.ob.p.inMe[lp.ob, xx - lp.lx, yy - lp.ly, lp.idx]
THEN
BEGIN
lp.selected ← TRUE;
selCount ← selCount + 1;
drawNewlySel[lp];
setupSelDisplay[lp];
RETURN;
END;
lp ← lp.nxt;
ENDLOOP;
END;
selNewThing: PUBLIC PROCEDURE [
mp, lp: LONG POINTER TO list, unOthers: BOOLEAN] =
BEGIN
IF unOthers THEN BEGIN undrawUnsel[mp]; selCount ← 0; END;
IF lp = NIL THEN RETURN;
lp.selected ← TRUE;
selCount ← selCount + 1;
setupSelDisplay[lp];
END;
unselSingle: PUBLIC PROCEDURE [mp: LONG POINTER TO list, xx, yy: INTEGER] =
BEGIN
lp ← mp;
WHILE lp # NIL DO
IF lp.selected AND lp.ob.p.inMe[lp.ob, xx - lp.lx, yy - lp.ly, lp.idx] THEN
BEGIN
nullifySelDisplay[];
lp.selected ← FALSE;
selCount ← selCount - 1;
reDrawRect[getRect[lp], 1, TRUE, TRUE, FALSE];
RETURN;
END;
lp ← lp.nxt;
ENDLOOP;
END;
selAreaSingle: PUBLIC PROCEDURE [mp: LONG POINTER TO list, xx, yy: INTEGER] =
BEGIN
x1, x2, y1, y2: INTEGER;
undrawUnsel[mp];
nullifySelDisplay[];
x1 ← MIN[xx, selMarkPnt.x];
y1 ← MIN[yy, selMarkPnt.y];
x2 ← MAX[xx, selMarkPnt.x];
y2 ← MAX[yy, selMarkPnt.y];
lp ← mp;
WHILE lp # NIL DO
IF inRect[lp, x1, y1, x2, y2] THEN
BEGIN lp.selected ← TRUE; selCount ← selCount + 1; drawNewlySel[lp]; END;
lp ← lp.nxt;
ENDLOOP;
END;
selAreaExtend: PUBLIC PROCEDURE [mp: LONG POINTER TO list, xx, yy: INTEGER] =
BEGIN
x1, x2, y1, y2: INTEGER;
nullifySelDisplay[];
x1 ← MIN[xx, selMarkPnt.x];
y1 ← MIN[yy, selMarkPnt.y];
x2 ← MAX[xx, selMarkPnt.x];
y2 ← MAX[yy, selMarkPnt.y];
lp ← mp;
WHILE lp # NIL DO
IF inRect[lp, x1, y1, x2, y2] AND NOT lp.selected THEN
BEGIN lp.selected ← TRUE; selCount ← selCount + 1; drawNewlySel[lp]; END;
lp ← lp.nxt;
ENDLOOP;
END;
unselAreaSingle: PUBLIC PROCEDURE [mp: LONG POINTER TO list, xx, yy: INTEGER] =
BEGIN
x1, x2, y1, y2: INTEGER;
nullifySelDisplay[];
x1 ← MIN[xx, selMarkPnt.x];
y1 ← MIN[yy, selMarkPnt.y];
x2 ← MAX[xx, selMarkPnt.x];
y2 ← MAX[yy, selMarkPnt.y];
lp ← mp;
WHILE lp # NIL DO
IF inRect[lp, x1, y1, x2, y2] AND lp.selected THEN
BEGIN
lp.selected ← FALSE;
selCount ← selCount - 1;
reDrawRect[getRect[lp], 1, TRUE, TRUE, FALSE];
END;
lp ← lp.nxt;
ENDLOOP;
END;
inRect: PROCEDURE [lp: LONG POINTER TO list, x1, y1, x2, y2: INTEGER]
RETURNS [BOOLEAN] =
BEGIN
x, y, sx, sy: INTEGER;
x ← lp.lx;
y ← lp.ly;
IF BITAND[lp.idx, 4] = 0 THEN
BEGIN sx ← lp.ob.size[0]; sy ← lp.ob.size[1]; END
ELSE BEGIN sx ← lp.ob.size[1]; sy ← lp.ob.size[0]; END;
IF x >= x2 OR y >= y2 OR x + sx <= x1 OR y + sy <= y1 THEN RETURN[FALSE];
IF x < x1 OR y < y1 OR x + sx > x2 OR y + sy > y2 THEN RETURN[FALSE];
RETURN[TRUE];
END;
localCellName: STRING ← [50];
DepletionStrengthName: PUBLIC PROC [imp: DepletionStrength] RETURNS [STRING] =
BEGIN
RETURN[(SELECT imp FROM
enhancement => "enh",
zeroThresh => "0-thresh",
weakDepletion => "wk depl",
strongDepletion => "depl",
ENDCASE => "?")];
END;
setupSelDisplay:PROCEDURE[lp: listPtr] =
BEGIN
localNameString.length ← 0;
AppendProps[to: localNameString, from: lp.props];
locIName ← localNameString;
localCellName.length ← 0;
WITH dob: lp.ob SELECT FROM
wire =>
BEGIN
AppendLevel[to: localCellName, from: dob.l];
AppendString[to: localCellName, from: " wire"];
locCell ← localCellName;
END;
rect =>
BEGIN
AppendLevel[to: localCellName, from: dob.l];
AppendString[to: localCellName, from: " rectangle"];
locCell ← localCellName;
END;
xstr =>
BEGIN
AppendString[to: localCellName, from: DepletionStrengthName[dob.impl]];
AppendString[to: localCellName, from: " "];
AppendLevel[to: localCellName, from: dob.l];
AppendString[to: localCellName, from: " xstr"];
locCell ← localCellName;
END;
cont =>
BEGIN
AppendLevel[to: localCellName, from: dob.l];
AppendString[to: localCellName, from: " contact"];
locCell ← localCellName;
END;
bus =>
BEGIN
AppendString[to: localCellName, from: ""];
AppendDecimal[s: localCellName, n: dob.wCnt];
AppendString[to: localCellName, from: "-wire "];
AppendLevel[to: localCellName, from: dob.l];
AppendString[to: localCellName, from: " bus"];
locCell ← localCellName;
END;
text => locCell←"text";
cnText => locCell←"cell name text";
cell =>
BEGIN
FOR cpp: cListPtr ← cellList, cpp.nxt WHILE cpp # NIL DO
IF lp.ob = cpp.ob THEN
BEGIN
AppendString[to: localCellName, from: "instance of cell "];
AppendString[to: localCellName, from: cpp.name];
locCell ← localCellName;
RETURN;
END;
ENDLOOP;
locCell←"instance of unnamed cell";
END;
ENDCASE => NULL;
END;
AppendLevel: PROC [to: STRING, from: level] =
BEGIN
AppendString[to: to, from: (SELECT from FROM
cut => "cut",
dif => "n-diffusion",
pol => "poly",
met => "metal",
imp => "depletion implant",
ovg => "overglass",
bur => "buried contact",
snerd => "?",
cut2 => "inter-metal via",
pdif => "p-diffusion",
pwelCont => "p-diffusion to substrate",
met2 => "metal2",
pwel => "p-substrate",
nwel => "n-well",
nwelCont => "n-diffusion to well",
ENDCASE => "unspecified")];
END;
nullifySelDisplay:PROCEDURE =
BEGIN
locIName←"";
locCell←"()";
END;
rotReflSel: PUBLIC PROCEDURE [refl: BOOLEAN] =
BEGIN rotReflList[refl, masterList, FALSE]; END;
rotReflList: PROCEDURE [
refl: BOOLEAN, mlp: LONG POINTER TO list, force: BOOLEAN] =
BEGIN
mix, miy, may, max, xx, yy, mdif: INTEGER;
flg: BOOLEAN ← FALSE;
ii: CARDINAL;
lp ← mlp;
WHILE lp # NIL DO
IF lp.selected OR force THEN
BEGIN
ii ← IF BITAND[lp.idx, 4] = 0 THEN 0 ELSE 1;
IF NOT flg THEN
BEGIN
mix ← lp.lx;
miy ← lp.ly;
may ← lp.ly + lp.ob.size[ii + 1];
max ← lp.lx + lp.ob.size[ii];
flg ← TRUE;
END
ELSE
BEGIN
mix ← MIN[mix, lp.lx];
miy ← MIN[miy, lp.ly];
may ← MAX[may, lp.ly + lp.ob.size[ii + 1]];
max ← MAX[max, lp.lx + lp.ob.size[ii]];
END;
END;
lp ← lp.nxt;
ENDLOOP;
mdif ← MAX[max - mix, may - miy];
lp ← mlp;
WHILE lp # NIL DO
IF lp.selected OR force THEN
BEGIN
ii ← IF BITAND[lp.idx, 4] = 0 THEN 0 ELSE 1;
anyChanges ← sinceIOchanges ← TRUE;
IF refl THEN
BEGIN
lp.idx ← BITXOR[lp.idx, 1];
lp.lx ← max - lp.lx + mix - lp.ob.size[ii];
END
ELSE
BEGIN
lp.idx ← BITAND[lp.idx + 4, 15];
IF BITAND[lp.idx, 1] # 0 THEN lp.idx ← BITXOR[lp.idx, 8];
xx ← lp.lx - mix;
yy ← lp.ly - miy;
lp.lx ← mix - yy - lp.ob.size[ii + 1] + may - miy;
lp.ly ← miy + xx;
END;
lp.ridx ← BITXOR[lp.idx, 1];
END;
lp ← lp.nxt;
ENDLOOP;
IF force THEN RETURN;
IF refl THEN reDrawRect[[mix, miy, max, may], 1, TRUE, TRUE, FALSE]
ELSE reDrawRect[[mix, miy, mix + mdif, miy + mdif], 1, TRUE, TRUE, FALSE];
END;
rotReflPnt: PUBLIC PROCEDURE [refl: BOOLEAN, xx, yy: INTEGER] =
BEGIN
mdif: INTEGER;
lp ← masterList;
WHILE lp # NIL DO
IF lp.ob.p.inMe[lp.ob, xx - lp.lx, yy - lp.ly, lp.idx] THEN
BEGIN
lp.idx ← IF refl THEN BITXOR[lp.idx, 1] ELSE BITAND[lp.idx + 4, 15];
lp.ridx ← BITXOR[lp.idx, 1];
mdif ← MAX[lp.ob.size[0], lp.ob.size[1]];
reDrawRect[
[lp.lx, lp.ly, lp.lx + mdif, lp.ly + mdif], 1, TRUE, TRUE, FALSE];
anyChanges ← sinceIOchanges ← TRUE;
RETURN;
END;
lp ← lp.nxt;
ENDLOOP;
END;
mergeRects: PUBLIC PROCEDURE [a, b: Rect] RETURNS [Rect] =
BEGIN
RETURN[[MIN[a.x1, b.x1], MIN[a.y1, b.y1], MAX[a.x2, b.x2], MAX[a.y2, b.y2]]];
END;
getRect: PUBLIC PROCEDURE [l: LONG POINTER TO list] RETURNS [r: Rect] =
BEGIN
ii: CARDINAL ← IF BITAND[l.idx, 4] = 0 THEN 0 ELSE 1;
oi:INTEGER←l.ob.surround;
r.x1 ← l.lx-oi;
r.y1 ← l.ly-oi;
r.x2 ← l.lx + l.ob.size[ii]+oi;
r.y2 ← l.ly + l.ob.size[ii + 1]+oi;
END;
cannonRect: PUBLIC PROCEDURE [r: Rect] RETURNS [Rect] =
BEGIN
t: INTEGER;
IF r.x1 > r.x2 THEN BEGIN t ← r.x1; r.x1 ← r.x2; r.x2 ← t; END;
IF r.y1 > r.y2 THEN BEGIN t ← r.y1; r.y1 ← r.y2; r.y2 ← t; END;
RETURN[r];
END;
makeList: PUBLIC PROCEDURE [
p: LONG POINTER TO object, x, y: INTEGER, o: orientation, refl: reflection]
RETURNS [lp: LONG POINTER TO list] =
BEGIN
lp ← alocList[];
lp↑.lx ← x;
lp↑.ly ← y;
lp↑.ob ← p;
lp↑.idx ← o*2 + refl;
lp↑.ridx ← BITXOR[1, lp.idx];
END;
putProp: PUBLIC PROC [lp: listPtr, attribute, value: Atom,
allowDuplAttr: BOOLEAN ← FALSE] =
BEGIN
IF attribute=NIL THEN
BEGIN
WHILE lp.props#NIL DO
victim: propPtr ← lp.props;
lp.props ← victim.next;
ppUncZone.FREE[@victim];
ENDLOOP;
END
ELSE
BEGIN
IF NOT allowDuplAttr THEN
BEGIN
pp: LONG POINTER TO propPtr ← @lp.props;
WHILE pp↑#NIL DO
IF pp.attribute=attribute THEN
BEGIN
victim: propPtr ← pp↑;
pp↑ ← victim.next;
ppUncZone.FREE[@victim];
END
ELSE pp ← @pp.next;
ENDLOOP;
END;
IF value#NIL THEN
lp.props ←
ppUncZone.NEW[prop ← [next: lp.props, attribute: attribute, value: value]];
END;
END;
AppendProps: PUBLIC PROC [to: LONG STRING, from: propPtr,
startPos: CARDINAL ← 0] =
BEGIN
NoMoreRoomInTo: ERROR = CODE;
Periods: PROC [n: CARDINAL] =
BEGIN
WHILE n>0 DO
IF to.maxlength<=to.length THEN ERROR NoMoreRoomInTo;
to[to.length] ← '.;
to.length ← to.length+1;
n ← n-1;
ENDLOOP;
END;
Append: PROC [s: LONG STRING] =
BEGIN
IF NOT started THEN
BEGIN
started ← TRUE;
IF startPos>0 THEN Periods[3];
END;
IF s.length<=startPos THEN startPos ← startPos-s.length
ELSE
BEGIN
FOR i: CARDINAL IN [startPos..s.length) DO
IF to.maxlength<=to.length+3 THEN Periods[4];
to[to.length] ← s[i];
to.length ← to.length+1;
ENDLOOP;
startPos ← 0;
END;
END;
started: BOOLEAN ← FALSE;
FOR p: propPtr ← from, p.next WHILE p#NIL DO
ENABLE NoMoreRoomInTo => GOTO Finished;
IF started THEN Append[", "];
Append[LOOPHOLE[p.attribute]];
Append[": "];
Append[LOOPHOLE[p.value]];
ENDLOOP;
EXITS Finished => NULL;
END; -- of AppendProps
inrect: PUBLIC PROCEDURE [x, y: INTEGER, lp: LONG POINTER TO list]
RETURNS [BOOLEAN] =
BEGIN
xs, ys: INTEGER;
IF BITAND[lp.idx, 4] = 0 THEN
BEGIN xs ← lp.ob.size[0]; ys ← lp.ob.size[1]; END
ELSE BEGIN xs ← lp.ob.size[1]; ys ← lp.ob.size[0]; END;
IF x IN [lp.lx..lp.lx + xs] AND y IN [lp.ly..lp.ly + ys] THEN RETURN[TRUE]
ELSE RETURN[FALSE];
END;
flushDel: PUBLIC PROCEDURE [lp: LONG POINTER TO list] =
BEGIN
lpp: LONG POINTER TO list;
WHILE lp # NIL DO
lp.ob.p.release[lp.ob];
lpp ← lp.nxt;
lp.deleted ← TRUE;
freeList[lp];
lp ← lpp;
ENDLOOP;
END;
--copy stuff:
copyObject: PUBLIC PROCEDURE [lp, mp: LONG POINTER TO list, xoff, yoff: INTEGER]
RETURNS [np: LONG POINTER TO list] =
BEGIN
np ← makeList[lp.ob.p.anotherme[lp.ob], lp.lx + xoff, lp.ly + yoff, 0, 0];
np.idx ← lp.idx;
np.ridx ← lp.ridx;
np.selected ← FALSE;
copyProps[np, lp];
np ← insertList[mp, np];
END;
copyProps: PUBLIC PROCEDURE [n, o: listPtr] =
BEGIN
n.props ← NIL;
FOR pop: propPtr ← o.props, pop.next WHILE pop # NIL DO
n.props ← ppUncZone.NEW[prop ←
[next: n.props, attribute: pop.attribute, value: pop.value]];
ENDLOOP;
END;
minmax: PUBLIC PROCEDURE [lp: LONG POINTER TO list]
RETURNS [mix, miy, max, may: INTEGER] =
BEGIN
flg: BOOLEAN ← TRUE;
ii: CARDINAL;
mix ← max ← miy ← may ← 0;
WHILE lp # NIL DO
ii ← IF BITAND[lp.idx, 4] = 0 THEN 0 ELSE 1;
IF flg THEN
BEGIN
mix ← lp.lx;
max ← lp.lx + lp.ob.size[ii];
miy ← lp.ly;
may ← lp.ly + lp.ob.size[ii + 1];
flg ← FALSE;
END
ELSE
BEGIN
mix ← MIN[mix, lp.lx];
max ← MAX[max, lp.lx + lp.ob.size[ii]];
miy ← MIN[miy, lp.ly];
may ← MAX[may, lp.ly + lp.ob.size[ii + 1]];
END;
lp ← lp.nxt;
ENDLOOP;
END;
typeInNum: PUBLIC PROCEDURE [os1, os2, os3: STRING]
RETURNS [bb: BOOLEAN, ii: INTEGER, ke: keyEvent] =
BEGIN
s:STRING;
i:CARDINAL;
[bb,s,ke]←typeIn[os1,os2,os3];
ii←0;
IF NOT bb THEN RETURN;
FOR i IN[0..s.length) DO
IF s[i] IN ['0..'9] THEN ii←ii*10+(s[i]-'0);
ENDLOOP;
IF s[0]='- THEN ii←-ii;
FreeString[s];
END;
typeIn: PUBLIC PROCEDURE [os1, os2, os3: STRING]
RETURNS [bb: BOOLEAN, is: STRING, ke: keyEvent] =
BEGIN
pos: CARDINAL;
invertColors[];
EraseArea[tiCx - 3, bwBottom+4, 700, bwMsgBottom-6];
pos ← ReplaceText[os1, tiCx, bwBottom + 20, fnt, normal];
pos ← ReplaceText[os2, tiCx, bwBottom + 30, fnt, normal];
pos ← ReplaceText[os3, tiCx, bwBottom + 40, fnt, normal];
[bb, is, ke] ← getstr[tiCx, bwBottom + 50];
IF bb THEN is ← newString[is] ELSE refreshTypeInScreen[];
restoreColors[];
END;
typeInC: PUBLIC PROCEDURE [os1, os2, os3: STRING] RETURNS [kk: keyEvent] =
BEGIN
pos: CARDINAL;
invertColors[];
EraseArea[tiCx - 3, bwBottom+4, 700, bwMsgBottom-6];
pos ← ReplaceText[os1, tiCx, bwBottom + 20, fnt, normal];
pos ← ReplaceText[os2, tiCx, bwBottom + 30, fnt, normal];
pos ← ReplaceText[os3, tiCx, bwBottom + 40, fnt, normal];
kk ← getchr[];
restoreColors[];
END;
typeOut: PUBLIC PROCEDURE [os1, os2, os3: STRING] =
BEGIN
pos: CARDINAL;
EraseArea[tiCx - 3, bwBottom+4, 700, bwMsgBottom-6];
pos ← ReplaceText[os1, tiCx, bwBottom + 20, fnt, normal];
pos ← ReplaceText[os2, tiCx, bwBottom + 30, fnt, normal];
pos ← ReplaceText[os3, tiCx, bwBottom + 40, fnt, normal];
END;
refreshTypeInScreen: PUBLIC PROCEDURE =
BEGIN
EraseArea[tiCx - 3, bwBottom+4, 700, bwMsgBottom-6];
END;
getErfil: PUBLIC cmdProc =
BEGIN
ok: BOOLEAN;
[ok, ss, ke] ← typeIn["", "Type Error File Name:", "(in full)"];
IF NOT ok THEN RETURN;
dChange ← TRUE;
IF NOT openErfile[ss] THEN RETURN;
END;
enterText: PUBLIC cmdProc =
BEGIN
IF NOT bb THEN RETURN;
FOR lp: listPtr ← masterList, lp.nxt WHILE lp # NIL DO
IF (lp.ob.otyp = wire OR lp.ob.otyp = cont)
AND lp.ob.p.inMe[lp.ob, xx - lp.lx, yy - lp.ly, lp.idx] THEN
{RequestItemProp[lp]; IF lp.selected THEN setupSelDisplay[lp]; RETURN};
ENDLOOP;
END;
enterName: PUBLIC cmdProc =
BEGIN
FOR lp: listPtr ← masterList, lp.nxt WHILE lp # NIL DO
IF lp.selected THEN
{RequestItemProp[lp]; setupSelDisplay[lp]; RETURN};
ENDLOOP;
END;
RequestItemProp: PROC [lp: listPtr] =
BEGIN OPEN ChipUserInt;
s: STRING ← NIL;
BEGIN
ParseAtom: PROC [start, beyondEnd: CARDINAL] RETURNS [Atom] =
BEGIN
WHILE start<beyondEnd AND s[start]=' DO start ← start+1 ENDLOOP;
WHILE start<beyondEnd AND s[beyondEnd-1]=' DO
beyondEnd ← beyondEnd-1;
ENDLOOP;
IF start<beyondEnd THEN
BEGIN
ts: STRING ← [200];
ts.length ← beyondEnd-start;
FOR i: CARDINAL IN [0..ts.length) DO ts[i] ← s[start+i] ENDLOOP;
RETURN[MakeAtom[ts]];
END
ELSE RETURN[NIL];
END; -- of ParseAtom
isSignal: BOOLEAN = SELECT lp.ob.otyp FROM
wire, cont => TRUE,
ENDCASE => FALSE;
firstColon: CARDINAL;
attribute, value: Atom;
s ← RequestString[
s1: "Enter attribute-value pair as ATTRIBUTE: VALUE"L,
initResult: (IF isSignal THEN "SIGNAL NAME: "L ELSE
"INSTANCE NAME: "L)
! Punt => GOTO ForgetIt];
firstColon ← s.length;
IF s.length>0 THEN
BEGIN
FOR i: CARDINAL IN [0..s.length) DO
IF s[i]=': THEN {firstColon ← i; EXIT};
ENDLOOP;
END;
attribute ← ParseAtom[0, firstColon];
value ← ParseAtom[firstColon+1, s.length];
IF attribute#NIL OR HeSaysYes["Shall I delete this node's entire property list?"L]
THEN
BEGIN
putProp[lp: lp, attribute: attribute, value: value, allowDuplAttr: FALSE];
anyChanges ← sinceIOchanges ← dChange ← TRUE;
END;
GOTO ForgetIt;
EXITS
ForgetIt => IF s#NIL THEN FreeString[s];
END;
END;
END.