--Cells6.mesa

--The example for naming wires is in ppprocs2.mesa, PROC=enterText:

DIRECTORY
  IODefs: FROM "IODefs",
  InlineDefs,
  ppdddefs,
  ppddefs,
  ppdefs,
  CellsDefs: FROM "CellsDefs";

Cells6:PROGRAM
 IMPORTS IODefs, InlineDefs, CellsDefs, ppdefs, ppddefs, ppdddefs
 EXPORTS CellsDefs=BEGIN OPEN CellsDefs;

Error:SIGNAL=CODE;
int:INTEGER=1;

max:INTEGER=13;
Everything:TYPE=RECORD[col,row,realName:INTEGER,term:ARRAY [0..max) OF Term];
nullEverything:Everything=[-1,-1,-1,ALL[[none,0,0,0]]];
Term:TYPE=RECORD[kind:Kind,r,g:Signal,off:INTEGER];
Kind:TYPE={none,nUp,nDn,pGn,pRd}; --labels what I am
Signal:TYPE=INTEGER;
dataType:TYPE=ARRAY [0..signalMax) OF Everything;
data:LONG POINTER TO dataType;
trueColumnType:TYPE=ARRAY [0..signalMax) OF INTEGER;
trueColumn:LONG POINTER TO trueColumnType;

SetEverything:PROCEDURE=BEGIN
npu:INTEGER;
data↑←ALL[nullEverything];
FOR s:INTEGER IN [0..signalMax) DO data[s].realName←s; ENDLOOP;
FOR s:INTEGER IN [8..signalMax) DO
  npu←-1;
  FOR z:TList←sig[s].def, z.next UNTIL z=NIL DO
    IF z.s.type = wire THEN
       {IF z.s.e#int THEN npu←z.s.e ELSE
              IF npu=-1 THEN Error ELSE data[z.s.d].realName←npu};
      ENDLOOP;
  ENDLOOP;
FOR s:INTEGER IN [8..signalMax) DO
  npu←-1;
  FOR z:TList←sig[s].def, z.next UNTIL z=NIL DO
    SELECT z.s.type FROM
        norPullUp=>npu←z.s.e;
        norPullDown=>{Set[npu,nUp,z.s.d,0]; Set[z.s.d,nDn,npu,0]};
        pass1=>{Set[z.s.e,pGn,z.s.d,z.s.g]; Set[z.s.d,pRd,z.s.e,z.s.g];
                Set[z.s.g,pGn,z.s.d,z.s.e]};
        ENDCASE;
      ENDLOOP;
  ENDLOOP;
EnumerateColumns[MarkIt];
FOR s:INTEGER IN [8..signalMax) DO
  ok:BOOLEAN←FALSE;
  c:INTEGER←sig[s].columnNum;
  IF data[s].col=-1 OR c=-1 THEN LOOP;
  FOR j:INTEGER IN Track DO IF track[c][j]='S THEN data[s].row←j; ENDLOOP;
  IF data[s].row=-1 THEN LOOP;
  FOR k:INTEGER IN [0..max) DO
    SELECT data[s].term[k].kind FROM none=>EXIT; pGn,nUp=>ok←TRUE; ENDCASE;
    ENDLOOP;
  IF ~ok THEN {--IF stop THEN Error;-- data[s].row←-1};
  ENDLOOP;
columnEnd←topTrack←0;
FOR s:INTEGER IN [8..signalMax) DO
  IF data[s].col=-1 THEN LOOP;
  columnEnd←MAX[columnEnd,data[s].col];
  topTrack←MAX[topTrack,data[s].row];
  ENDLOOP;
FOR s:INTEGER IN [8..signalMax) DO
  IF data[s].col=-1 THEN LOOP;
  FOR k:INTEGER IN [0..max) DO
    t:Term=data[s].term[k];
    SELECT t.kind FROM
      none=>EXIT;
      nUp,nDn=>data[s].term[k].r← data[t.r].realName;
      pGn,pRd=>data[s].term[k]
                  ←[t.kind,data[t.r].realName,data[t.g].realName,0];
      ENDCASE=>Error;
    ENDLOOP;
  ENDLOOP;
trueColumn↑←ALL[-1];
FOR s:INTEGER IN [8..signalMax)
  DO c:INTEGER←data[s].col; IF c#-1 THEN trueColumn[c]←s; ENDLOOP;
FOR c:INTEGER IN [0..columnEnd] DO IF c=-1 THEN Error; ENDLOOP;
END;

MarkIt:PROCEDURE[c,s,z:INTEGER]=
  {IF data[s].realName#s THEN Error; data[s].col←z};

Set:PROCEDURE[i:INTEGER,z:Kind,j,k:INTEGER]=BEGIN
i←data[i].realName; j←data[j].realName; k←data[k].realName;
FOR t:INTEGER IN [0..max) DO
  IF data[i].term[t].kind=none THEN {data[i].term[t]←[z,j,k,0]; RETURN};
  ENDLOOP;
Error;--parameter "max" too small
END;

Showtrack:PUBLIC PROCEDURE=BEGIN
done←second←FALSE;
SetEverything[];
SortTerms[];
MakeOff[];
Fudge[];
topX←topTrack*7+base+4+4;
IF chip THEN BEGIN
  ok: BOOLEAN;
  ULAName: STRING ← NIL;
  [ok, ULAName, ] ← ppdefs.typeIn[""L, ""L, "Name of completed ULA cell:"L];
  ShowASection[0,0];
  DrawCell[MakeNewCell[ULAName, lpp].ob];
  ULAName ← NIL;  -- we gave the name to the cell
  RETURN;
  END;
FOR j:INTEGER←0, j+yMax UNTIL j>=colly[columnEnd]+16 DO ShowASection[4,j]; ENDLOOP;
END;

ShowASection:PROCEDURE[x,y:INTEGER]=BEGIN
grid←ALL[ALL[EmptyGrid]];
lowerLeftX←x; lowerLeftY←y;
BlueWires[];
RedWires[];
Transistors[];
GroundWires[];
Pullups[];
Contacts[];
PrintGrid[];
PowerAndGround[];
END;

colly:ARRAY [0..columnMax) OF INTEGER;

--Fudge:PROCEDURE=BEGIN
--FOR i:INTEGER IN [0..columnMax) DO colly[i]←8*i; ENDLOOP;
--END;


Fudge:PROCEDURE=BEGIN
second:BOOLEAN←FALSE;
colly[0]←0;
FOR i:INTEGER IN [0..columnEnd-1] DO
  found,foundP:BOOLEAN←FALSE;
  s:INTEGER←trueColumn[i];
  ss:INTEGER←trueColumn[i+1];
  w:INTEGER←1;
  FOR k:INTEGER IN [0..max) DO
    SELECT data[s].term[k].kind FROM none=>EXIT; nUp=>found←TRUE; ENDCASE;
    ENDLOOP;
  FOR k:INTEGER IN [0..max) DO
    SELECT data[ss].term[k].kind FROM none=>EXIT; nUp=>foundP←TRUE; ENDCASE;
    ENDLOOP;
  SELECT TRUE FROM
     ~found => second←FALSE;
     ~second => second←TRUE;
     ~foundP=> NULL;
     ENDCASE=>{w←2; second←FALSE};
  IF i MOD 2 =0 THEN FOR k:INTEGER IN [0..max) DO
    t:Term←data[s].term[k];
    gnd:BOOLEAN←t.kind=nDn;
    r,z:INTEGER;
    SELECT t.kind FROM
      nDn=>{r←data[t.r].row; z←10000};
      pRd=>{r←MIN[data[t.r].row,data[t.g].row]; z←MAX[data[t.r].row,data[t.g].row]};
      ENDCASE=>EXIT;
    w←MAX[w,t.off];
    FOR l:INTEGER IN [0..max) DO
      tt:Term=data[ss].term[l];
      SELECT tt.kind FROM
        nDn=>IF gnd OR z<data[tt.r].row THEN LOOP;
        pRd=>IF z<MIN[data[tt.r].row,data[tt.g].row]
             OR r>MAX[data[tt.r].row,data[tt.g].row] THEN  LOOP;
        ENDCASE=>EXIT;
        w←MAX[w,t.off+tt.off];
      ENDLOOP;
    ENDLOOP;
  colly[i+1]←colly[i]+8*w;
  ENDLOOP;
END;

SortTerms:PROCEDURE=BEGIN
FOR s:INTEGER IN [8..signalMax) DO
  IF data[s].col=-1 THEN LOOP;
  FOR k:INTEGER IN [0..max) DO
    t:Term←data[s].term[k];
    r:INTEGER;
    SELECT t.kind FROM
      none=>EXIT;
      nDn=>r←data[t.r].row;
      pRd=>r←MIN[data[t.r].row,data[t.g].row];
      ENDCASE=>r←-1;
    FOR l:INTEGER IN (k..max) DO
      tt:Term=data[s].term[l];
      rr:INTEGER;
      SELECT tt.kind FROM
        none=>EXIT;
        nDn=>rr←data[tt.r].row;
        pRd=>rr←MIN[data[tt.r].row,data[tt.g].row];
        ENDCASE=>rr←-1;
      IF rr>r THEN {data[s].term[l]←t; data[s].term[k]←t←tt; r←rr};
      ENDLOOP;
    ENDLOOP;
  ENDLOOP;
END;

MakeOff:PROCEDURE=BEGIN
FOR s:INTEGER IN [8..signalMax) DO
  IF data[s].col=-1 THEN LOOP;
  FOR k:INTEGER IN [0..max) DO
    t:Term=data[s].term[k];
    off:INTEGER←1;
    r:INTEGER;
    SELECT t.kind FROM
      nDn=>r←10000;
      pRd=>r←MAX[data[t.r].row,data[t.g].row];
      ENDCASE=>EXIT;
    FOR l:INTEGER IN [0..k) DO
      tt:Term=data[s].term[l];
      rr:INTEGER;
      SELECT tt.kind FROM
        nDn=>rr←data[tt.r].row;
        pRd=>rr←MIN[data[tt.r].row,data[tt.g].row];
        ENDCASE=>EXIT;
      IF r<rr THEN EXIT;
      IF r=10000 AND tt.kind=nDn THEN off←MAX[off,tt.off]
                    ELSE off←MAX[off,tt.off+1];
      ENDLOOP;
    data[s].term[k].off←off;
    ENDLOOP;
  ENDLOOP;
FOR s:INTEGER IN [8..signalMax) DO
  IF data[s].col=-1 THEN LOOP;
  FOR k:INTEGER IN [0..max) DO t:Term=data[s].term[k];
    ss:INTEGER←t.r;
    SELECT t.kind FROM
      nDn=>FOR j:INTEGER IN [0..max) DO tt:Term=data[ss].term[j];
          IF tt.kind=nUp AND tt.r=s THEN {data[ss].term[j].off←t.off; EXIT};
          ENDLOOP;
      pRd=>BEGIN
        FOR j:INTEGER IN [0..max) DO tt:Term=data[ss].term[j];
          IF tt.kind=pGn AND tt.r=s THEN {data[ss].term[j].off←t.off; EXIT};
          ENDLOOP;
        ss←t.g;
        FOR j:INTEGER IN [0..max) DO tt:Term=data[ss].term[j];
          IF tt.kind=pGn AND tt.r=s THEN {data[ss].term[j].off←t.off; EXIT};
          ENDLOOP;
        END;
      ENDCASE=>EXIT;
    ENDLOOP;
  ENDLOOP;
END;

PowerAndGround:PROCEDURE=BEGIN
BlueWire[0,0,4,colly[columnEnd]+10];
AssignName[savedThis,"VDD"];
BlueWire[topX,0,topX+4,colly[columnEnd]+10];
AssignName[savedThis,"GND"];
END;

BlueWires:PROCEDURE=BEGIN
c,x,yLo,yHi,qy:INTEGER;
FOR i:INTEGER IN [8..signalMax) DO
  wierd:BOOLEAN←FALSE;
  IF data[i].col=-1 THEN LOOP;
  c←data[i].col;
  yHi←yLo←colly[c]+1;
  FOR k:INTEGER IN [0..max) DO
    t:Term=data[i].term[k];
    q:INTEGER←data[t.r].col;
    qEven:BOOLEAN= q MOD 2 = 0;
    up:BOOLEAN;
    SELECT t.kind FROM
      none=>EXIT;
      nDn,pRd=>LOOP;
      nUp=>up← ~qEven;
      pGn=>up← SELECT data[i].row-data[t.g].row FROM
           >0=>qEven, 0=>c>q, ENDCASE=>~qEven;
      ENDCASE=>Error;
    qy←colly[q]+(IF up THEN 7 ELSE -1);
    IF up=qEven THEN
      {qy←IF up THEN qy+8*(t.off-1) ELSE qy-8*(t.off-1); wierd←TRUE};
    yHi←MAX[yHi,qy-4];
    yLo←MIN[yLo,qy];
    ENDLOOP;
  x←base+data[i].row*7+1;
  IF wierd OR yHi-yLo>4 THEN BlueWire[x,yLo,x+3,yHi]
  ENDLOOP;
END;

signalName:INTEGER←-1;

RedWires:PROCEDURE=BEGIN
q,maxR,minR:INTEGER;
y,xLo,xHi:INTEGER;
pull:BOOLEAN;
FOR i:INTEGER IN [8..signalMax) DO
  c:INTEGER=data[i].col;  r:INTEGER=data[i].row;
  IF c=-1 THEN LOOP;
  signalName←i;
  y←colly[c];
  IF r=-1 THEN {RedWire[0,y,topX+4,y+2]; LOOP};
  q←maxR←minR←r;
  pull←FALSE;
  FOR k:INTEGER IN [0..max) DO
    t:Term=data[i].term[k];
    SELECT t.kind FROM
      none=>EXIT;
      nUp=>{pull←TRUE; LOOP};
      nDn=>q←data[t.r].row;
      pGn=>LOOP;
      pRd=>q←MIN[data[t.r].row,data[t.g].row];
      ENDCASE=>Error;
    IF q<0 THEN Error;
    maxR←MAX[maxR,q];
    minR←MIN[minR,q];
    ENDLOOP;
  xHi←base+maxR*7+4;
  xLo←IF pull THEN base-2 ELSE base+minR*7;
  IF xHi-xLo<=4 THEN RedWire[0,y,topX+4,y+2] ELSE RedWire[xLo,y,xHi,y+2]
  ENDLOOP;
END;

Transistors:PROCEDURE=BEGIN
q:INTEGER;
y:INTEGER;
FOR i:INTEGER IN [8..signalMax) DO
  c:INTEGER=data[i].col;  r:INTEGER=data[i].row;
  IF c=-1 THEN LOOP;
  y←colly[c];
  FOR k:INTEGER IN [0..max) DO
    t:Term=data[i].term[k];
    SELECT t.kind FROM
      none=>EXIT;
      nUp=>LOOP;
      nDn=>q←data[t.r].row;
      pGn=>LOOP;
      pRd=>q←MIN[data[t.r].row,data[t.g].row];
      ENDCASE=>Error;
    IF q<0 THEN Error;
    Transistor[base+q*7,y];
    ENDLOOP;
  ENDLOOP;
END;

GroundWires:PROCEDURE=BEGIN
y:INTEGER;
FOR c:INTEGER IN [0..columnMax) DO
  i:INTEGER←trueColumn[c];
  IF i<8 THEN LOOP;
  y←colly[c]+(IF c MOD 2 = 0 THEN 3 ELSE -5);
  FOR k:INTEGER IN [0..max) DO
    t:Term=data[i].term[k];
    yy:INTEGER←y+8*(IF c MOD 2 = 0 THEN t.off-1 ELSE -t.off+1);
    r1:INTEGER←data[t.r].row;
    r2:INTEGER←data[t.g].row;
    minX,maxX:INTEGER;
    SELECT t.kind FROM
      none=>EXIT;
      nUp=>LOOP;
      nDn=>{minX←base+r1*7; maxX←topX};
      pGn=>LOOP;
      pRd=>{minX←base+MIN[r1,r2]*7; maxX←base+MAX[r1,r2]*7};
      ENDCASE=>Error;
    GreenWire[minX,yy,maxX,yy+4];
    GreenBlueContact[maxX,yy];
    IF t.off=1 THEN LOOP;
    IF c MOD 2 = 0 THEN GreenWire[minX,y,minX+4,yy]
                   ELSE GreenWire[minX,yy+4,minX+4,y+4];
    ENDLOOP;
  ENDLOOP;
END;

Pullups:PROCEDURE=BEGIN
edge:INTEGER←5;
second:BOOLEAN←FALSE;
FOR c:INTEGER IN [0..columnMax) DO
  found:BOOLEAN←FALSE;
  i:INTEGER←trueColumn[c];
  y:INTEGER←colly[c];
  IF i<8 THEN LOOP;
  FOR k:INTEGER IN [0..max) DO
    SELECT data[i].term[k].kind FROM
      none=>EXIT;
      nUp=>{found←TRUE; EXIT};
      ENDCASE;
    ENDLOOP;
  IF found AND  second THEN Pullup2[edge,y];
  IF found AND ~second THEN
    {Pullup1[edge,y]; GreenWire[0,y+4,edge+5,y+6]; GreenBlueContact[0,y+3]};
  second←found AND ~second;
  ENDLOOP;
END;

Contacts:PROCEDURE=BEGIN
FOR i:INTEGER IN [8..signalMax) DO
  c:INTEGER=data[i].col;  r:INTEGER=data[i].row;
  IF ~(c=-1 OR r=-1) THEN BEGIN
  even:BOOLEAN=c MOD 2 = 0;
  done:BOOLEAN←FALSE;
  y:INTEGER=colly[c];
  x:INTEGER=base+r*7;
  FOR k:INTEGER IN [0..max) DO
    t:Term=data[i].term[k];
    q:INTEGER=data[t.r].col;
    qEven:BOOLEAN=q MOD 2 = 0;
    yk:INTEGER=IF q=-1 THEN 0 ELSE colly[q];
    rowOffset:INTEGER=data[i].row-data[t.g].row;
    SignalChannel:PROCEDURE=BEGIN
       IF ~qEven AND q#c-1 THEN {GreenBlueContact[x,yk+3]; RETURN};
       IF  qEven AND q#c+1 THEN {GreenBlueContact[x,yk-5]; RETURN};
       IF even THEN ThreeWay2[x,y-5] ELSE ThreeWay1[x,y+1];
       IF even
         THEN {IF y#colly[c-1]+8 THEN GreenWire[x,colly[c-1]+3,x+4,y-5]}
         ELSE {IF y#colly[c+1]-8 THEN GreenWire[x,y+7,x+4,colly[c+1]-1]};
       done←TRUE;
       END;
    FindOffset:PROCEDURE RETURNS[off:INTEGER]=BEGIN
      FOR kk:INTEGER IN [0..max) DO
        tTerm:Term←data[t.r].term[kk];
        SELECT tTerm.kind FROM
                 nUp,pGn,none=>EXIT;
                 pRd=>IF tTerm.r=t.g AND tTerm.g=i
                         OR tTerm.r=i AND tTerm.g=t.g
                         THEN {off←tTerm.off; RETURN};
                 ENDCASE;
        ENDLOOP;
      RETURN[1];
      END;
    SELECT t.kind FROM
      none=>EXIT;
      nUp=>SignalChannel[];
      nDn=>NULL;
      pGn=>IF rowOffset>0 OR rowOffset=0 AND (c>q)=qEven
          THEN BEGIN
             offY:INTEGER←8*(FindOffset[]-1);
             yy:INTEGER=IF qEven THEN 3+offY ELSE -5-offY;
             GreenBlueContact[x,yk+yy];
             END
          ELSE SignalChannel[];
      pRd=>NULL;
      ENDCASE=>Error;
    ENDLOOP;
  IF ~done THEN RedBlueContact[x,y-(IF even THEN 2 ELSE 0)];
  END; ENDLOOP;
END;



lowerLeftX,lowerLeftY:INTEGER;
yMax:INTEGER=40;
xMax:INTEGER=64;
grid:ARRAY [0..yMax) OF PACKED ARRAY [0..xMax) OF Grid;
Grid:TYPE=RECORD [r,b,g,x:YesNo];
EmptyGrid:Grid=[n,n,n,n];
YesNo:TYPE={y,n};
done,second:BOOLEAN;
base:INTEGER=14;
topX,topTrack,columnEnd:INTEGER; 

Pullup1:PROCEDURE[x,y:INTEGER]=BEGIN
IF chip THEN
   lpp ← ppddefs.insertList[lpp, ppdddefs.makeList[ppdddefs.makePullup[4,8], (x+1)*2, (y-5)*2, 4, 0]];
ShowRecD[red,x,y-2,8,4];
ShowRecD[green,x+2,y-5,4,3];
ShowRecD[x,x+3,y-4,2,4];
ShowRecD[green,x+3,y+2,2,2];
END;

Pullup2:PROCEDURE[x,y:INTEGER]=BEGIN
IF chip THEN
  lpp ← ppddefs.insertList[lpp, ppdddefs.makeList[ppdddefs.makePullup[4,8], (x+1)*2, (y-2)*2, 0, 0]];
ShowRecD[red,x,y,8,4];
ShowRecD[green,x+2,y+4,4,3];
ShowRecD[x,x+3,y+2,2,4];
ShowRecD[green,x+3,y-2,2,2];
END;

ThreeWay1:PROCEDURE[x,y:INTEGER]=BEGIN
IF chip THEN
  lpp ← ppddefs.insertList[lpp, ppdddefs.makeList[ppdddefs.makeButcon[], x*2, (y)*2, 0, 0]];
ShowRecD[blue,x,y,4,6];
ShowRecD[red,x,y,4,3];
ShowRecD[green,x,y+3,4,3];
ShowRecD[x,x+1,y+1,2,4];
END;

ThreeWay2:PROCEDURE[x,y:INTEGER]=BEGIN
IF chip THEN
  lpp ← ppddefs.insertList[lpp, ppdddefs.makeList[ppdddefs.makeButcon[], x*2, (y)*2, 4, 0]];
ShowRecD[blue,x,y,4,6];
ShowRecD[green,x,y,4,3];
ShowRecD[red,x,y+3,4,3];
ShowRecD[x,x+1,y+1,2,4];
END;

RedBlueContact:PROCEDURE[x,y:INTEGER]=BEGIN
IF chip THEN
  lpp ← ppddefs.insertList[lpp, ppdddefs.makeList[ppdddefs.makePolycon[4], x*2, (y)*2, 0, 0]];
ShowRecD[blue,x,y,4,4];
ShowRecD[red,x,y,4,4];
ShowRecD[x,x+1,y+1,2,2];
END;

GreenBlueContact:PROCEDURE[x,y:INTEGER]=BEGIN
IF chip THEN
  lpp ← ppddefs.insertList[lpp, ppdddefs.makeList[ppdddefs.makeDifcon[4], x*2, (y)*2, 0, 0]];
ShowRecD[blue,x,y,4,4];
ShowRecD[green,x,y,4,4];
ShowRecD[x,x+1,y+1,2,2];
END;

Transistor:PROCEDURE[x,y:INTEGER]=BEGIN
IF chip THEN
  lpp ← ppddefs.insertList[lpp, ppdddefs.makeList[ppdddefs.makeXstr[8,4], (x-2)*2, (y-2)*2, 0, 0]];
ShowRecD[red,x-2,y,8,2];
ShowRecD[green,x,y-2,4,6];
END;
savedThis:LONG POINTER TO ppdefs.list←NIL;

ChipWire:PROCEDURE[c:Color,x1,y1,x2,y2:INTEGER]=BEGIN
OPEN ppdefs, ppddefs, ppdddefs;
IF ~chip THEN RETURN ELSE BEGIN
myLevel:level=SELECT c FROM green=>dif,red=>pol, ENDCASE=>met;
deltaX:INTEGER=ABS[x2-x1];
deltaY:INTEGER=ABS[y2-y1];
orient:INTEGER=IF deltaX > deltaY THEN 2 ELSE 0;
l:INTEGER=2*(IF deltaX > deltaY THEN deltaX ELSE deltaY);
w:INTEGER=2*(IF deltaX > deltaY THEN deltaY ELSE deltaX);
this:LONG POINTER TO list←makeList[makeWire[l,w,myLevel],2*x1,2*y1,orient,0];
savedThis←this;
lpp ← insertList[lpp,this];
IF c=red AND signalName#-1 THEN AssignName[this,Lookup2[signalName]];
END; END;

AssignName:PROCEDURE[this:LONG POINTER TO ppdefs.list,s:STRING]=BEGIN
OPEN ppdefs, ppddefs, ppdddefs;
IF chip THEN BEGIN
putProp[lp:this, attribute:MakeAtom["SIGNAL NAME"L], value:MakeAtom[s]];
END; END;

GreenWire:PROCEDURE[x1,y1,x2,y2:INTEGER]=
     {ChipWire[green,x1,y1,x2,y2]; ShowRec[green,x1,y1,x2,y2]};

RedWire:  PROCEDURE[x1,y1,x2,y2:INTEGER]=
     {ChipWire[red,x1,y1,x2,y2]; ShowRec[red,x1,y1,x2,y2]};

BlueWire: PROCEDURE[x1,y1,x2,y2:INTEGER]=
     {ChipWire[blue,x1,y1,x2,y2]; ShowRec[blue,x1,y1,x2,y2]};


Color:TYPE={red,blue,green,x};

ShowRecD:PROCEDURE[color:Color,x1,y1,x2,y2:INTEGER]=
   {ShowRec[color,x1,y1,x1+x2,y1+y2]};

ShowRec:PROCEDURE[color:Color,x1,y1,x2,y2:INTEGER]=BEGIN
IF chip THEN RETURN;
x1←MAX[x1-lowerLeftX,0]; y1←MAX[y1-lowerLeftY,0];
x2←MIN[x2-lowerLeftX,xMax]; y2←MIN[y2-lowerLeftY,yMax];
IF ~(x1<x2 AND y1<y2) THEN RETURN;
FOR i:INTEGER IN [x1..x2) DO
  FOR j:INTEGER IN [y1..y2) DO
      SELECT color FROM
        blue => grid[j][i].b←y; 
         red => grid[j][i].r←y; 
       green => grid[j][i].g←y; 
       ENDCASE => grid[j][i].x←y; 
    ENDLOOP;
  ENDLOOP;
END;

PrintGrid:PROCEDURE=BEGIN
IF chip OR ~printPlot THEN RETURN;
FOR j:INTEGER IN [0..yMax) DO
IODefs.WriteChar[Ret]; 
  FOR i:INTEGER IN [0..xMax) DO
    IF grid[j][i].x=y THEN IODefs.WriteChar['x]
       ELSE SELECT grid[j][i] FROM
        [n,n,n,n] => IODefs.WriteChar[Space]; 
        [n,n,y,n] => IODefs.WriteChar['g]; 
        [n,y,n,n] => IODefs.WriteChar['B]; 
        [n,y,y,n] => IODefs.WriteChar['G]; 
        [y,n,n,n] => IODefs.WriteChar['r]; 
        [y,n,y,n] => IODefs.WriteChar['t]; 
        [y,y,n,n] => IODefs.WriteChar['R]; 
        [y,y,y,n] => IODefs.WriteChar['T]; 
       ENDCASE => IODefs.WriteChar['?]; 
    ENDLOOP;
  ENDLOOP;
END;

lpp: LONG POINTER TO ppdefs.list ← NIL;  -- list of cells already placed

MakeNewCell: PROCEDURE [name: STRING, lpp: LONG POINTER TO ppdefs.list]
    RETURNS [cp: LONG POINTER TO ppdefs.cList] =
    BEGIN OPEN ppdefs, ppddefs, ppdddefs;
    min: Point ← [LAST[locNum], LAST[locNum]];
    max: Point ← [FIRST[locNum], FIRST[locNum]];
    FOR lp: LONG POINTER TO list ← 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: LONG POINTER TO list ← 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

  DrawCell: PROCEDURE [obp: LONG POINTER TO ppdefs.object] =
    BEGIN OPEN ppdefs, ppddefs, ppdddefs;
    lp: LONG POINTER TO list ← makeList[obp.p.anotherme[obp], xx, yy, 0, 0];
    obp.returnable ← FALSE;
    masterList ← insertList[masterList, lp];
    anyChanges ← sinceIOchanges ← TRUE;
    selNewThing[masterList, lp, TRUE];
    putMark[xx, yy];
    reDrawRect[getRect[lp], 0, TRUE, TRUE, FALSE];
    END;  -- of DrawCell

InitStorage:PROCEDURE=BEGIN
data←zone.NEW[dataType];
trueColumn←zone.NEW[trueColumnType];
END;

InitStorage;
END..