-- procedure exporting module of silicon (pretty picture) program
-- last modified by McCreight, December 3, 1982  9:40 AM
--  to remove repeated objects

DIRECTORY
  InlineDefs,
  SegmentDefs,
  StringDefs,
  ppdddefs,ppddefs,
  pppdefs,
  ppdefs;
ppprocs: PROGRAM IMPORTS ppdefs, ppddefs, ppdddefs, InlineDefs, pppdefs
  EXPORTS ppdefs,ppdddefs =
  BEGIN OPEN ppdefs, ppdddefs,ppddefs, SegmentDefs, InlineDefs, pppdefs;

  anyChanges, sinceIOchanges: PUBLIC BOOLEAN ← FALSE;

  Width: TYPE = locNum ← 0;
  minWidthAr: PUBLIC ARRAY level OF Width ← [
    cut: 2*Lambda,
    dif: 2*Lambda,
    pol: 2*Lambda,
    met: 3*Lambda,
    cut2: 3*Lambda,
    pdif: 2*Lambda,
    met2: 4*Lambda];

  bwGrain: PUBLIC INTEGER ← 10;
  colGrain: PUBLIC INTEGER ← 1;


  wireList: PUBLIC ARRAY level OF LONG POINTER TO wire object ← ALL[NIL];
  tranList: PUBLIC LONG POINTER TO xstr object ← NIL;
  puList: PUBLIC LONG POINTER TO xstr object ← NIL;
  contList: PUBLIC LONG POINTER TO cont object ← NIL;

  textProcs:Procs ← [
    drawme:ALL[drText],inBox:rectIB,inMe:inMeRect,release:nullRel,
    anotherme:permAnother,setParm:setNullParm];
  rectProcs:Procs ← [
    drawme:[
    drRect0,drRect0,drRect0,drRect0,drRect2,drRect2,drRect2,drRect2,
    drRect0,drRect0,drRect0,drRect0,drRect2,drRect2,drRect2,drRect2],
    inBox:rectIB,inMe:inMeRect,release:refCntRelease,anotherme:permAnother,
    setParm:setWireParm];
  xstrProcs:Procs ← [
    drawme:[
    drXstr0,drXstr0,drXstr0,drXstr0,drXstr2,drXstr2,drXstr2,drXstr2,
    drXstr0,drXstr0,drXstr0,drXstr0,drXstr2,drXstr2,drXstr2,drXstr2],
    inBox:rectIB,inMe:inMeRect,release:refCntRelease,anotherme:permAnother,
    setParm:setXstrParm];
  pxstrProcs:Procs ← [
    drawme:[
    drXstr0,drXstr0,drXstr0,drXstr0,drXstr2,drXstr2,drXstr2,drXstr2,
    drXstr0,drXstr0,drXstr0,drXstr0,drXstr2,drXstr2,drXstr2,drXstr2],
    inBox:rectIB,inMe:inMeRect,release:refCntRelease,anotherme:permAnother,
    setParm:setPXstrParm];
  angxstrProcs:Procs ← [
    drawme:[
    drAXstr0,drAXstrR0,drAXstr0,drAXstrR0,drAXstr2,drAXstrR2,drAXstr2,drAXstrR2,
    drAXstr4,drAXstrR4,drAXstr4,drAXstrR4,drAXstr6,drAXstrR6,drAXstr6,drAXstrR6],
    inBox:rectIB,inMe:inMeRect,release:refCntRelease,anotherme:permAnother,
    setParm:setAXstrParm];

  cellProcs:Procs ← [
    drawme:[
    drCell0,drCell0R,drCell0,drCell0R,drCell2,drCell2R,drCell2,drCell2R,
    drCell4,drCell4R,drCell4,drCell4R,drCell6,drCell6R,drCell6,drCell6R],
    inBox:rectIB,inMe:inMeRect,release:cellRel,anotherme:permAnother,
    setParm:setNullParm];
  wireProcs:Procs ← [
    drawme:[
    drWire0,drWire0,drWire0,drWire0,drWire2,drWire2,drWire2,drWire2,
    drWire0,drWire0,drWire0,drWire0,drWire2,drWire2,drWire2,drWire2],
    inBox:rectIB,inMe:inMeRect,release:refCntRelease,anotherme:permAnother,
    setParm:setWireParm];
  pwireProcs:Procs ← [
    drawme:[
    drPWire0,drPWire0,drPWire0,drPWire0,drPWire2,drPWire2,drPWire2,drPWire2,
    drPWire0,drPWire0,drPWire0,drPWire0,drPWire2,drPWire2,drPWire2,drPWire2],
    inBox:rectIB,inMe:inMeRect,release:refCntRelease,anotherme:permAnother,
    setParm:setWireParm];

  busProcs:Procs ← [
    drawme:[
    drBus0,drBusR0,drBus0,drBusR0,drBus2,drBusR2,drBus2,drBusR2,
    drBus4,drBusR4,drBus4,drBusR4,drBus6,drBusR6,drBus6,drBusR6],
    inBox:rectIB,inMe:inMeRect,release:uniqueRelease,anotherme:busAnother,
    setParm:setBusParm];
  puProcs:Procs ← [
    drawme:[
    drPu0,drPu0,drPu0,drPu0,drPu2,drPu6,drPu2,drPu6,drPu4,drPu4,drPu4,
    drPu4,drPu6,drPu2,drPu6,drPu2],inBox:rectIB,inMe:inMeRect,
    release:refCntRelease,anotherme:permAnother,setParm:setPuParm];
  bcProcs:Procs ← [
    drawme:[
    drBC0,drBC0,drBC0,drBC0,drBC2,drBC6,drBC2,drBC6,drBC4,drBC4,drBC4,
    drBC4,drBC6,drBC2,drBC6,drBC2],inBox:rectIB,inMe:inMeRect,
    release:nullRel,anotherme:permAnother,setParm:setNullParm];
  mcProcs:Procs ← [
    drawme:[
    drMDC0,drMDC0,drMDC0,drMDC0,drMDC2,drMDC2,drMDC2,drMDC2,drMDC0,drMDC0,
    drMDC0,drMDC0,drMDC2,drMDC2,drMDC2,drMDC2],inBox:rectIB,inMe:inMeRect,
    release:refCntRelease,anotherme:permAnother,setParm:setContParm];
  dcProcs:Procs ← [
    drawme:[
    drDC0,drDC0,drDC0,drDC0,drDC2,drDC2,drDC2,drDC2,drDC0,drDC0,drDC0,
    drDC0,drDC2,drDC2,drDC2,drDC2],inBox:rectIB,inMe:inMeRect,
    release:refCntRelease,anotherme:permAnother,setParm:setContParm];
  mpdcProcs:Procs ← [
    drawme:[
    drMPDC0,drMPDC0,drMPDC0,drMPDC0,drMPDC2,drMPDC2,drMPDC2,drMPDC2,
	drMPDC0,drMPDC0,drMPDC0,
    drMPDC0,drMPDC2,drMPDC2,drMPDC2,drMPDC2],inBox:rectIB,inMe:inMeRect,
    release:refCntRelease,anotherme:permAnother,setParm:setContParm];
  pdcProcs:Procs ← [
    drawme:[
    drPDC0,drPDC0,drPDC0,drPDC0,drPDC2,drPDC2,drPDC2,drPDC2,
	drPDC0,drPDC0,drPDC0,
    drPDC0,drPDC2,drPDC2,drPDC2,drPDC2],inBox:rectIB,inMe:inMeRect,
    release:refCntRelease,anotherme:permAnother,setParm:setContParm];
  bucProcs:Procs ← [
    drawme:[
    drBuC0,drBuC4,drBuC0,drBuC4,drBuC2,drBuC2,drBuC2,drBuC2,
	drBuC4,drBuC0,drBuC4,drBuC0,drBuC6,drBuC6,drBuC6,drBuC6],
	inBox:rectIB,inMe:inMeRect,
    release:refCntRelease,anotherme:permAnother,setParm:setBuContParm];
  mmcProcs:Procs ← [
    drawme:[
    drMM0,drMM0,drMM0,drMM0,drMM2,drMM2,drMM2,drMM2,drMM0,drMM0,drMM0,
    drMM0,drMM2,drMM2,drMM2,drMM2],inBox:rectIB,inMe:inMeRect,
    release:refCntRelease,anotherme:permAnother,setParm:setContParm];
  bcObject:cont object ← [
    p:@bcProcs,size:[butconSX,butconSY,butconSX],l:cut,refCnt:0,
    returnable:FALSE,marked:FALSE,
    varpart:cont[typ:butt,magicN:butconSX/4]];
  cnTextProcs:Procs ← [
    drawme:ALL[drCnText],inBox:rectIB,inMe:inMeRect,release:cnRelease,
    anotherme:permAnother,setParm:setNullParm];

  nullRel: relProc = BEGIN ob.refCnt ← ob.refCnt - 1; END;
  refCntRelease: relProc =
    BEGIN
    ob.refCnt ← ob.refCnt - 1;
    --	IF ob.refCnt>1 THEN ob.refCnt←ob.refCnt-1
    --	 ELSE FreeSpace[ob];
    END;
  cellRel: relProc =
    BEGIN
    cc: LONG POINTER TO cell object;
    ob.refCnt ← ob.refCnt - 1;
    IF ob.refCnt > 0 OR NOT ob.returnable THEN RETURN;
    cc ← LOOPHOLE[ob];
    flushDel[cc.ptr];
    freeCell[cc];
    END;
  cnRelease: relProc =
    BEGIN
    p: LONG POINTER TO cnText object = LOOPHOLE[ob];
    FreeString[p.s];
    FreeSpace[ob];
    END;
  uniqueRelease: relProc =
    BEGIN
    FreeSpace[ob];
    END;

  permAnother: anoProc = BEGIN ob.refCnt ← ob.refCnt + 1; RETURN[ob]; END;
  busAnother: anoProc =
    BEGIN
    nob:LONG POINTER TO bus object ← alocBusD[];
    oob:LONG POINTER TO bus object = LOOPHOLE[ob];
    nob↑←oob↑;
    RETURN[nob];
    END;

  makePullup: PUBLIC PROCEDURE [w,l:INTEGER,wExt:INTEGER←wXExtension,lExt:INTEGER←lXExtension]
    RETURNS [p: LONG POINTER TO object] =
    BEGIN
    dp: LONG POINTER TO xstr object ← puList;
    w ← MAX[w, 2*Lambda];
    l ← MAX[l, 2*Lambda];
    wExt ← MAX[wExt, 0];
    lExt ← MAX[lExt, 0];
    WHILE dp # NIL DO
      IF dp.width = w AND dp.length = l
         AND dp.wExt = wExt AND dp.lExt = lExt AND dp.l=dif
	 THEN BEGIN p ← dp.p.anotherme[dp]; RETURN; END;
      dp ← dp.super;
      ENDLOOP;
    p ← dp ← alocXstrD[];
    dp.super ← puList;
    puList ← dp;
    p↑.p ← @puProcs;
    dp↑.l ← dif;
    dp↑.width ← w;
    dp↑.length ← l;
    dp↑.wExt ← wExt;
    dp↑.lExt ← lExt;
    dp↑.impl ← TRUE;
    dp↑.pullup ← TRUE;
    dp↑.size[0] ← dp↑.size[2] ←
      MAX[dp.width + dp.wExt*2, 4*Lambda];
    dp↑.size[1] ← MAX[dp.length + dp.lExt + 3*Lambda, 6*Lambda];
    END; -- of makePullup

  makeXstr: PUBLIC PROCEDURE [w, l: INTEGER, imp: BOOLEAN ← FALSE
    , wExt: INTEGER ← wXExtension, lExt: INTEGER ← lXExtension]
    RETURNS [p: LONG POINTER TO object] =
    BEGIN
    dp: LONG POINTER TO xstr object ← tranList;
    w ← MAX[w, 2*Lambda];
    l ← MAX[l, 2*Lambda];
    wExt ← MAX[wExt, 0];
    lExt ← MAX[lExt, 0];
    WHILE dp # NIL DO
      IF dp.width = w AND dp.length = l AND dp.impl = imp
         AND dp.wExt = wExt AND dp.lExt = lExt AND NOT dp.angle AND dp.l=dif
        THEN
        BEGIN p ← dp.p.anotherme[dp]; RETURN; END;
      dp ← dp.super;
      ENDLOOP;
    p ← dp ← alocXstrD[];
    dp.super ← tranList;
    tranList ← dp;
    p↑.p ← @xstrProcs;
    dp↑.l ← dif;
    dp↑.width ← w;
    dp↑.length ← l;
    dp↑.wExt ← wExt;
    dp↑.lExt ← lExt;
    dp↑.impl ← imp;
    dp↑.pullup ← FALSE;
    dp↑.size[0] ← dp↑.size[2] ← dp.width + dp.wExt*2;
    dp↑.size[1] ← dp.length + dp.lExt*2;
    END; -- of makeXstr

  makeAngleXstr: PUBLIC PROCEDURE [w, l: INTEGER, imp: BOOLEAN ← FALSE
    , wExt: INTEGER ← wXExtension, lExt: INTEGER ← lXExtension,aExt:INTEGER←0]
    RETURNS [p: LONG POINTER TO object] =
    BEGIN
    dp: LONG POINTER TO xstr object ← tranList;
    siz1:INTEGER;
    wExt ← MAX[wExt, 0];
    lExt ← MAX[lExt, 0];
    aExt ← MAX[aExt, -lExt];
    l ← MAX[l, 2*Lambda];
    w ← MAX[w, 2*lExt]; -- the width of the straight-line
      -- parts of the gate, excluding the corner
    siz1 ← wExt+2*lExt+aExt+l;
    WHILE dp # NIL DO
      IF dp.width = w AND dp.length = l AND dp.impl = imp AND dp.wExt=wExt
	 AND dp.lExt=lExt AND dp.angle AND dp.size[1]=siz1 AND dp.l=dif
        THEN
        BEGIN p ← dp.p.anotherme[dp]; RETURN; END;
      dp ← dp.super;
      ENDLOOP;
    p ← dp ← alocXstrD[];
    dp.super ← tranList;
    tranList ← dp;
    p↑.p ← @angxstrProcs;
    dp↑.l ← dif;
    dp↑.width ← w;
    dp↑.length ← l;
    dp↑.wExt ← wExt;
    dp↑.lExt ← lExt;
    dp↑.impl ← imp;
    dp↑.angle ← TRUE;
    dp↑.pullup ← FALSE;
    dp↑.size[0] ← dp↑.size[2] ← wExt+(w-lExt-aExt)+l+lExt;
    dp↑.size[1] ← siz1;
    END;

  makePXstr: PUBLIC PROCEDURE [w,l:INTEGER,imp:BOOLEAN←FALSE,
	wExt:INTEGER←wXExtension,lExt:INTEGER←lXExtension
	,surr:INTEGER←wellSurround]
    RETURNS [p: LONG POINTER TO object] =
    BEGIN
    dp: LONG POINTER TO xstr object ← tranList;
    w ← MAX[w, 2*Lambda];
    l ← MAX[l, 2*Lambda];
    wExt ← MAX[wExt, 0];
    lExt ← MAX[lExt, 0];
    WHILE dp # NIL DO
      IF dp.width = w AND dp.length = l AND dp.impl = imp
         AND dp.wExt = wExt AND dp.lExt = lExt AND NOT dp.angle AND dp.l=pdif
        AND dp.surround=surr THEN
        BEGIN p ← dp.p.anotherme[dp]; RETURN; END;
      dp ← dp.super;
      ENDLOOP;
    p ← dp ← alocXstrD[];
    dp.super ← tranList;
    tranList ← dp;
    p↑.p ← @pxstrProcs;
    dp↑.l ← pdif;
    dp↑.surround ← surr;
    dp↑.width ← w;
    dp↑.length ← l;
    dp↑.wExt ← wExt;
    dp↑.lExt ← lExt;
    dp↑.impl ← imp;
    dp↑.pullup ← FALSE;
    dp↑.size[0] ← dp↑.size[2] ← w + dp.wExt*2;
    dp↑.size[1] ← l + dp.lExt*2;
    END;

  makeRect: PUBLIC PROCEDURE [x, y: INTEGER, l: level]
    RETURNS [p: LONG POINTER TO object] =
    BEGIN
    dp: LONG POINTER TO rect object;
    x ← MAX[x, 1];
    y ← MAX[y, 1];
    p ← dp ← alocRectD[];
    p↑.p ← @rectProcs;
    dp↑.size[0] ← dp↑.size[2] ← x;
    dp↑.size[1] ← y;
    dp↑.l ← l;
    END;

  makeText: PUBLIC PROCEDURE [s: STRING] RETURNS [p: LONG POINTER TO object] =
    BEGIN
    dp: LONG POINTER TO text object;
    p ← dp ← alocTextD[];
    p↑.p ← @textProcs;
    dp↑.size[0] ← dp↑.size[2] ← 6*s.length;
    dp↑.size[1] ← 8;
    dp↑.s ← s;
    dp↑.l ← cut;
    END;

  makeCnText: PUBLIC PROCEDURE [
    s: STRING, xw, byw, yw: INTEGER, op: LONG POINTER TO cell object,
    np: LONG POINTER TO cList] RETURNS [p: LONG POINTER TO object] =
    BEGIN
    dp: LONG POINTER TO cnText object;
    p ← dp ← alocCnTextD[];
    p↑.p ← @cnTextProcs;
    dp↑.size[0] ← xw;
    dp↑.size[1] ← byw;
    dp↑.size[2] ← byw*yw;
    dp↑.s ← newString[s];
    dp↑.np ← np;
    dp↑.op ← op;
    END;

  makeButcon: PUBLIC PROCEDURE RETURNS [p: LONG POINTER TO object] =
    BEGIN p ← @bcObject; p.refCnt ← p.refCnt + 1; END;
  makePolycon: PUBLIC PROCEDURE [lll: INTEGER]
    RETURNS [p: LONG POINTER TO object] =
    BEGIN
    dp: LONG POINTER TO cont object ← contList;
    IF lll < butconSX THEN lll ← butconSX;
    WHILE dp # NIL DO
      IF dp.size[1] = lll AND dp.typ = mPol THEN
        BEGIN p ← dp.p.anotherme[dp]; RETURN; END;
      dp ← dp.super;
      ENDLOOP;
    p ← dp ← alocContD[];
    dp.super ← contList;
    contList ← dp;
    dp.size[0] ← dp.size[2] ← butconSX;
    dp.size[1] ← lll;
    dp.p ← @dcProcs;
    dp.typ ← mPol;
    dp.magicN ← butconSX/4;
    dp.l←pol
    END;
  makeDifcon: PUBLIC PROCEDURE [lll: INTEGER]
    RETURNS [p: LONG POINTER TO object] =
    BEGIN
    dp: LONG POINTER TO cont object ← contList;
    IF lll < butconSX THEN lll ← butconSX;
    WHILE dp # NIL DO
      IF dp.size[1] = lll AND dp.typ = mDif THEN
        BEGIN p ← dp.p.anotherme[dp]; RETURN; END;
      dp ← dp.super;
      ENDLOOP;
    p ← dp ← alocContD[];
    dp.super ← contList;
    contList ← dp;
    dp.size[0] ← dp.size[2] ← butconSX;
    dp.size[1] ← lll;
    dp.p ← @dcProcs;
    dp.typ ← mDif;
    dp.magicN ← butconSX/4;
    dp.l←dif
    END;
  makeMmDifcon: PUBLIC PROCEDURE [lll: INTEGER]
    RETURNS [p: LONG POINTER TO object] =
    BEGIN
    mins:INTEGER=cut2min+2*mmContExt;
    dp: LONG POINTER TO cont object ← contList;
    IF lll < mins THEN lll ← mins;
    WHILE dp # NIL DO
      IF dp.size[1] = lll AND dp.typ = mmDif THEN
        BEGIN p ← dp.p.anotherme[dp]; RETURN; END;
      dp ← dp.super;
      ENDLOOP;
    p ← dp ← alocContD[];
    dp.super ← contList;
    contList ← dp;
    dp.size[0] ← dp.size[2] ← mins;
    dp.size[1] ← lll;
    dp.p ← @mcProcs;
    dp.typ ← mmDif;
    dp.magicN ← (mins-4)/2;
    dp.m2Ext ← (mins-butconSX)/2;
    dp.c2Ext ← mmContExt;
    dp.l←dif
    END;
  makeMmPolcon: PUBLIC PROCEDURE [lll: INTEGER]
    RETURNS [p: LONG POINTER TO object] =
    BEGIN
    mins:INTEGER=cut2min+2*mmContExt;
    dp: LONG POINTER TO cont object ← contList;
    IF lll < mins THEN lll ← mins;
    WHILE dp # NIL DO
      IF dp.size[1] = lll AND dp.typ = mmPol THEN
        BEGIN p ← dp.p.anotherme[dp]; RETURN; END;
      dp ← dp.super;
      ENDLOOP;
    p ← dp ← alocContD[];
    dp.super ← contList;
    contList ← dp;
    dp.size[0] ← dp.size[2] ← mins;
    dp.size[1] ← lll;
    dp.p ← @mcProcs;
    dp.typ ← mmPol;
    dp.magicN ← (mins-4)/2;
    dp.m2Ext ← (mins-butconSX)/2;
    dp.c2Ext ← mmContExt;
    dp.l←pol
    END;
  makeNwellcon: PUBLIC PROCEDURE [lll: INTEGER]
    RETURNS [p: LONG POINTER TO object] =
    BEGIN
    dp: LONG POINTER TO cont object ← contList;
    IF lll < butconSX THEN lll ← butconSX;
    WHILE dp # NIL DO
      IF dp.size[1] = lll AND dp.typ = nwell THEN
        BEGIN p ← dp.p.anotherme[dp]; RETURN; END;
      dp ← dp.super;
      ENDLOOP;
    p ← dp ← alocContD[];
    dp.super ← contList;
    contList ← dp;
    dp.size[0] ← dp.size[2] ← butconSX;
    dp.size[1] ← lll;
    dp.p ← @dcProcs;
    dp.typ ← nwell;
    dp.magicN ← butconSX/4;
    dp.l←nwelCont
    END;
  makePDifcon: PUBLIC PROCEDURE [lll: INTEGER,surr:INTEGER←wellSurround]
    RETURNS [p: LONG POINTER TO object] =
    BEGIN
    dp: LONG POINTER TO cont object ← contList;
    IF lll < butconSX THEN lll ← butconSX;
    WHILE dp # NIL DO
      IF dp.size[1] = lll AND dp.typ = mPDif AND dp.surround=surr THEN
        BEGIN p ← dp.p.anotherme[dp]; RETURN; END;
      dp ← dp.super;
      ENDLOOP;
    p ← dp ← alocContD[];
    dp.super ← contList;
    contList ← dp;
    dp.size[0] ← dp.size[2] ← butconSX;
    dp.size[1] ← lll;
    dp.p ← @pdcProcs;
    dp.typ ← mPDif;
    dp.magicN ← butconSX/4;
    dp.l←pdif;
    dp.surround←surr;
    END;
  makeMPDifcon: PUBLIC PROCEDURE [lll: INTEGER,surr:INTEGER←wellSurround]
    RETURNS [p: LONG POINTER TO object] =
    BEGIN
    dp: LONG POINTER TO cont object ← contList;
    mins:INTEGER=cut2min+2*mmContExt;
    IF lll < mins THEN lll ← mins;
    WHILE dp # NIL DO
      IF dp.size[1] = lll AND dp.typ = mmPDif AND dp.surround=surr THEN
        BEGIN p ← dp.p.anotherme[dp]; RETURN; END;
      dp ← dp.super;
      ENDLOOP;
    p ← dp ← alocContD[];
    dp.super ← contList;
    contList ← dp;
    dp.size[0] ← dp.size[2] ← mins;
    dp.size[1] ← lll;
    dp.surround←surr;
    dp.p ← @mpdcProcs;
    dp.typ ← mmPDif;
    dp.magicN ← (mins-4)/2;
    dp.m2Ext ← (mins-butconSX)/2;
    dp.c2Ext ← mmContExt;
    dp.l←pdif
    END;
  makeBuCont: PUBLIC PROCEDURE [wid,len,wex,lex: INTEGER]
    RETURNS [p: LONG POINTER TO object] =
    BEGIN
    dp: LONG POINTER TO cont object ← contList;
    IF wex<0 THEN wex←0;IF lex<0 THEN lex←0;
    IF wid < 2*wex+2 THEN wid ← 2*wex+2;
    IF len < 2*lex+4 THEN len ← 2*lex+4;
    WHILE dp # NIL DO
      IF dp.typ=burr AND dp.size[1] = len AND dp.size[0] = wid AND
		dp.wExt=wex AND dp.lExt=lex THEN
        BEGIN p ← dp.p.anotherme[dp]; RETURN; END;
      dp ← dp.super;
      ENDLOOP;
    p ← dp ← alocContD[];
    dp.super ← contList;
    contList ← dp;
    dp.size[0] ← dp.size[2] ← wid;
    dp.size[1] ← len;
    dp.p ← @bucProcs;
    dp.typ ← burr;
    dp.wExt←wex;
    dp.lExt←lex;
    dp.magicN←IF wid>=2*wex+4 THEN 0 ELSE 2*wex+4-wid;
    END;
  makeMmCont: PUBLIC PROCEDURE [len,wex,lex: INTEGER]
    RETURNS [p: LONG POINTER TO object] =
    BEGIN
    mins:INTEGER=cut2min+2*mmContExt;
    dp: LONG POINTER TO cont object ← contList;
    IF len < mins THEN len ← mins;
--    IF wex<0 THEN wex←0;IF lex<0 THEN lex←0;
--    IF wid < 2*wex+2 THEN wid ← 2*wex+2;
--    IF len < 2*lex+4 THEN len ← 2*lex+4;
    WHILE dp # NIL DO
      IF dp.typ=mm2 AND dp.size[1] = len --AND dp.size[0] = wid AND
		--dp.wExt=wex AND dp.lExt=lex --THEN
        BEGIN p ← dp.p.anotherme[dp]; RETURN; END;
      dp ← dp.super;
      ENDLOOP;
    p ← dp ← alocContD[];
    dp.super ← contList;
    contList ← dp;
    dp.size[0] ← dp.size[2] ← mins;
    dp.size[1] ← len;
    dp.p ← @mmcProcs;
    dp.typ ← mm2;
--    dp.wExt←wex;
--    dp.lExt←lex;
    dp.magicN←mmContExt;
    END;
  makeWire:PUBLIC PROCEDURE[len,wid:INTEGER,l:level,surr:INTEGER←wellSurround]
    RETURNS [p: LONG POINTER TO object] =
    BEGIN
    dc: LONG POINTER TO wire object;
    IF wireOK[l]--=dif OR l=pol OR l=met OR l=met2-- THEN
      BEGIN
      dc ← wireList[l];
      WHILE dc # NIL DO
        IF dc.size[0] = wid AND dc.size[1] = len
		AND (l#pdif OR dc.surround=surr) THEN
          BEGIN p ← dc.p.anotherme[dc]; RETURN; END;
        dc ← dc.super;
        ENDLOOP;
      END;
    p ← dc ← alocWireD[];
    IF wireOK[l] THEN BEGIN dc.super ← wireList[l]; wireList[l] ← dc; END;
    p↑.p ← IF NOT wireOK[l] THEN @rectProcs ELSE IF l=pdif THEN
	@pwireProcs ELSE @wireProcs;
--    IF l=pdif THEN {dc.size[0]←dc.size[2]←wid+2*tubMinExt;
--		dc.size[1]←len+2*tubMinExt;}
     -- ELSE {--dc↑.size[0] ← dc↑.size[2] ← wid;
		dc↑.size[1] ← len;--};
    dc.surround←IF l=pdif THEN surr ELSE 0;
    dc↑.l ← l;
    END;
  makeBus: PUBLIC PROCEDURE [len, wid: INTEGER, l: level, cnt, spc, tinc, binc: INTEGER]
    RETURNS [p: LONG POINTER TO object] =
    BEGIN
    b: LONG POINTER TO bus object;
    p ← b ← alocBusD[];
    p↑.p ← @busProcs;
    b.wspace ← spc;
    b.firstLength ← len;
    b.topIncr ← tinc;
    b.lenIncr ← binc - tinc;
    b.wwidth ← wid;
    b.wCnt ← cnt;
    p.l ← l;
    setBusSizes[b];
    END;
  setBusSizes:PROCEDURE[p:LONG POINTER TO bus object] =
    BEGIN
    binc:INTEGER←p.lenIncr+p.topIncr;
    p.offsetFirst ← IF p.topIncr>=0 THEN 0 ELSE (1-p.wCnt)*p.topIncr;
    p.size[0] ← p.size[2] ← (p.wCnt-1)*p.wspace + p.wwidth;
    p.size[1] ← IF binc>0 THEN p.offsetFirst+p.firstLength+(p.wCnt-1)*binc
	ELSE p.offsetFirst+p.firstLength;
    END;

  makeRep: PUBLIC PROC [ob:obPtr,winc,linc,dx,dy,cnt:INTEGER,
    idx:orientationIndex] RETURNS [p: LONG POINTER TO object] =
    BEGIN
    repeat: cellPtr ← p ← makeCell[sx: 0, sy: 0, cnt: cnt, ptr: NIL];
    FOR i: INTEGER IN [0..cnt) DO
      repeat.ptr ← insertList[mp: repeat.ptr,
        lp: makeList[p: ob.p.anotherme[ob], x: i*dx, y: i*dy,
          o: idx/2, refl: idx MOD 2]];
      ENDLOOP;
    [max: repeat.size[0], may: repeat.size[1]] ← minmax[repeat.ptr];
    repeat.size[2] ← repeat.size[0]; -- sigh!
    END;

  makeCell: PUBLIC PROCEDURE [
    sx, sy: INTEGER, cnt: CARDINAL, ptr: LONG POINTER TO list]
    RETURNS [p: LONG POINTER TO cell object] =
    BEGIN
    dc: LONG POINTER TO cell object;
    p ← dc ← alocCellD[];
    p↑.p ← @cellProcs;
    dc↑.ptr ← ptr;
    dc↑.size[0] ← dc↑.size[2] ← sx;
    dc↑.size[1] ← sy;
    dc↑.l ← cut;
    dc↑.cnt ← cnt;
    END;


  inMeRect: inMeProc =  --tells if cursor(or whatever)at x,y is inside object
    BEGIN
    xs, ys: INTEGER;
    IF BITAND[o, 4] = 0 THEN BEGIN xs ← ob.size[0]; ys ← ob.size[1]; END
    ELSE BEGIN xs ← ob.size[1]; ys ← ob.size[0]; END;
    IF x IN [0..xs] AND y IN [0..ys] THEN RETURN[TRUE] ELSE RETURN[FALSE];
    END;

  rectIB: ibProc =
    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];
    RETURN[TRUE];
    END;

  setWireParm: parmProc =
    BEGIN
    dp: LONG POINTER TO wire object ← LOOPHOLE[lp.ob];
    nw, nl, wd, ln, mn: INTEGER;
    l: level ← dp.l;
	movl:BOOLEAN←FALSE;
    wd ← dp.size[0];
    ln ← dp.size[1];
    SELECT pt FROM
      width => BEGIN nl ← ln; nw ← (wd*dy) + dx; END;
      length => BEGIN nl ← (ln*dy) + dx; nw ← wd; END;
      default =>
        BEGIN
        IF NOT wireOK[l] THEN RETURN[FALSE];
        nl ← ln;
        nw ← minWidthAr[l];
        END;
      wSpace => BEGIN nl ← ln; nw ← wd + dx; END;
      ENDCASE => RETURN[FALSE];
    IF nw < INTEGER[lambdaGrid] THEN nw ← lambdaGrid;
    IF nl<1 THEN {IF nl<0 THEN {movl←TRUE;nl←-nl} ELSE nl←Lambda;};
--    IF l=pdif THEN {IF nw<INTEGER[lambdaGrid]+2*tubMinExt THEN
--	nw←lambdaGrid+2*tubMinExt;
--	IF nl<2*tubMinExt+1 THEN nl←2*tubMinExt+1;};
    IF nw = wd AND nl = ln THEN RETURN[FALSE];
    mn ← 2*lambdaGrid;
    IF BITAND[lp.idx, 4] = 0 THEN
      BEGIN
	IF cent THEN {lp.lx ← lp.lx + lambdaGrid*(wd/mn - nw/mn);
		lp.ly ← lp.ly + lambdaGrid*(ln/mn - nl/mn);};
	IF movl THEN lp.ly ← lp.ly - nl;
      END
    ELSE
      BEGIN
        IF cent THEN {lp.lx ← lp.lx + lambdaGrid*(ln/mn - nl/mn);
		lp.ly ← lp.ly + lambdaGrid*(wd/mn - nw/mn);};
	IF movl THEN lp.lx ← lp.lx - nl;
      END;
    RETURN[NewObject[lp, makeWire[nl, nw, l]]];
    END;

  NewObject: PROCEDURE [lp: listPtr, ob: obPtr] RETURNS [BOOLEAN] =
    BEGIN
    lp.ob.p.release[lp.ob];
    lp.ob ← ob;
    RETURN[TRUE];
    END;

  setBusParm: parmProc =
    BEGIN
    dp: LONG POINTER TO bus object ← LOOPHOLE[lp.ob];
    nw, nl, wd, ln, mn: INTEGER;
    l: level ← dp.l;
    wd ← dp.wwidth;
    ln ← dp.firstLength;
    SELECT pt FROM
      width => BEGIN nl ← ln; nw ← (wd*dy) + dx; END;
      length => BEGIN nl ← (ln*dy) + dx; nw ← wd; END;
      default =>
        BEGIN
        IF NOT (l=dif OR l=pol OR l=met OR l=met2) THEN RETURN[FALSE];
        nl ← ln;
        nw ← minWidthAr[l];
        END;
      ENDCASE =>
	BEGIN
	    SELECT pt FROM
		wSpace => BEGIN dp.wspace←dp.wspace + dx; IF dp.wspace<dp.wwidth+1 THEN dp.wspace←dp.wwidth+1; END;
		count => BEGIN dp.wCnt←dp.wCnt + dx; IF dp.wCnt<1 THEN dp.wCnt←1; END;
		lSpace => BEGIN dp.topIncr←dp.topIncr + dx; END;
		bSpace => BEGIN dp.lenIncr←dp.lenIncr + dx; END;
	      ENDCASE;
	    setBusSizes[dp];
	    RETURN[TRUE];
	END;
    IF nw < INTEGER[lambdaGrid] THEN nw ← lambdaGrid;
    IF nl < 1 THEN nl ← 1;
    IF nw = wd AND nl = ln THEN RETURN[FALSE];
    mn ← 2*lambdaGrid;
    IF BITAND[lp.idx, 4] = 0 AND cent THEN
      BEGIN
      lp.lx ← lp.lx + lambdaGrid*(wd/mn - nw/mn);
      lp.ly ← lp.ly + lambdaGrid*(ln/mn - nl/mn);
      END
    ELSE
      IF cent THEN
        BEGIN
        lp.lx ← lp.lx + lambdaGrid*(ln/mn - nl/mn);
        lp.ly ← lp.ly + lambdaGrid*(wd/mn - nw/mn);
        END;
    dp.size[0] ← dp.size[2] ← dp.size[0] + nw - wd;
    dp.size[1] ← dp.size[1] +  nl - ln;
    dp.wwidth ← nw;
    dp.firstLength ← nl;
    RETURN[TRUE];
    END;

  setNullParm: parmProc = BEGIN RETURN[FALSE]; END;

  setAXstrParm: parmProc =
    BEGIN
    dp: LONG POINTER TO xstr object ← LOOPHOLE[lp.ob];
    nw, nl, wd, ln, mn,nwe,nle,nax,oax: INTEGER;
    im: BOOLEAN ← dp.impl;
    nw←wd ← dp.width;
    nl←ln ← dp.length;
    nwe←dp.wExt;
    nle←dp.lExt;
    oax←nax←dp.size[1]-dp.length-2*dp.lExt-dp.wExt;
    SELECT pt FROM
      width => BEGIN nw ← (wd*dy) + dx; END;
      length => BEGIN nw ← (wd*dy) + dx; nax←nax+nw-wd;END;
      default => BEGIN nl ← cLength*xRatiol; nw ← cWidth*xRatiow; nax←0;
		nwe←wXExtension;nle←lXExtension;END;
      wSpace => BEGIN IF -dx>dp.wExt THEN dx←-dp.wExt;nwe←dp.wExt+dx; END;
      lSpace => BEGIN IF -dx>dp.lExt THEN dx←-dp.lExt;nle←dp.lExt+dx; END;
      count => BEGIN im←IF dx<0 THEN FALSE ELSE TRUE; END;
      ENDCASE => RETURN[FALSE];
    -- new parameter ranges now tested in makeAngleXstr
    IF nw = wd AND nl = ln AND dp.wExt=nwe AND dp.lExt=nle
	AND oax=nax AND dp.impl=im THEN RETURN[FALSE];
    mn ← 2*lambdaGrid;
    IF BITAND[lp.idx, 4] = 0 AND cent THEN
      BEGIN
      lp.lx ← lp.lx + lambdaGrid*((wd-oax)/mn - (nw-nax)/mn);
      lp.ly ← lp.ly + lambdaGrid*(oax/mn - nax/mn);
      END
    ELSE
      IF cent THEN
        BEGIN
        lp.lx ← lp.lx + lambdaGrid*(oax/mn - nax/mn);
        lp.ly ← lp.ly + lambdaGrid*((wd-oax)/mn - (nw-nax)/mn);
        END;
    RETURN[NewObject[lp, makeAngleXstr[nw, nl, im,nwe,nle,nax]]];
    END;

  setXstrParm: parmProc =
    BEGIN
    dp: LONG POINTER TO xstr object ← LOOPHOLE[lp.ob];
    nw, nl, wd, ln, mn,nwe,nle: INTEGER;
    im: BOOLEAN ← dp.impl;
    nw←wd ← dp.width;
    nl←ln ← dp.length;
    nwe←dp.wExt;
    nle←dp.lExt;
    SELECT pt FROM
      width => BEGIN nw ← (wd*dy) + dx; END;
      length => BEGIN nl ← (ln*dy) + dx; END;
      default => BEGIN nl ← cLength*xRatiol; nw ← cWidth*xRatiow;
		nwe←wXExtension;nle←lXExtension;END;
      wSpace => BEGIN IF -dx>dp.wExt THEN dx←-dp.wExt;nwe←dp.wExt+dx; END;
      lSpace => BEGIN IF -dx>dp.lExt THEN dx←-dp.lExt;nle←dp.lExt+dx; END;
      count => BEGIN im←IF dx<0 THEN FALSE ELSE TRUE; END;
      ENDCASE => RETURN[FALSE];
    -- new parameter ranges now tested in makeXstr
    IF nw = wd AND nl = ln AND dp.wExt=nwe AND dp.lExt=nle AND dp.impl=im THEN RETURN[FALSE];
    mn ← 2*lambdaGrid;
    IF BITAND[lp.idx, 4] = 0 AND cent THEN
      BEGIN
      lp.lx ← lp.lx + lambdaGrid*(wd/mn - nw/mn);
      lp.ly ← lp.ly + lambdaGrid*(ln/mn - nl/mn);
      END
    ELSE
      IF cent THEN
        BEGIN
        lp.lx ← lp.lx + lambdaGrid*(ln/mn - nl/mn);
        lp.ly ← lp.ly + lambdaGrid*(wd/mn - nw/mn);
        END;
    RETURN[NewObject[lp, makeXstr[nw, nl, im,nwe,nle]]];
    END;

  setPXstrParm: parmProc =
    BEGIN
    dp: LONG POINTER TO xstr object ← LOOPHOLE[lp.ob];
    nw, nl, wd, ln, mn,nwe,nle: INTEGER;
    im: BOOLEAN ← dp.impl;
    nw←wd ← dp.width;
    nl←ln ← dp.length;
    nwe←dp.wExt;
    nle←dp.lExt;
    SELECT pt FROM
      width => BEGIN nw ← (wd*dy) + dx; END;
      length => BEGIN nl ← (ln*dy) + dx; END;
      default => BEGIN nl ← cLength*xRatiol; nw ← cWidth*xRatiow;
		nwe←wXExtension;nle←lXExtension;END;
      wSpace => BEGIN IF -dx>dp.wExt THEN dx←-dp.wExt;nwe←dp.wExt+dx; END;
      lSpace => BEGIN IF -dx>dp.lExt THEN dx←-dp.lExt;nle←dp.lExt+dx; END;
      count => BEGIN im←IF dx<0 THEN FALSE ELSE TRUE; END;
      ENDCASE => RETURN[FALSE];
    -- new parameter ranges now tested in makePXstr
    IF nw = wd AND nl = ln AND dp.wExt=nwe AND dp.lExt=nle AND dp.impl=im THEN RETURN[FALSE];
    mn ← 2*lambdaGrid;
    IF BITAND[lp.idx, 4] = 0 AND cent THEN
      BEGIN
      lp.lx ← lp.lx + lambdaGrid*(wd/mn - nw/mn);
      lp.ly ← lp.ly + lambdaGrid*(ln/mn - nl/mn);
      END
    ELSE
      IF cent THEN
        BEGIN
        lp.lx ← lp.lx + lambdaGrid*(ln/mn - nl/mn);
        lp.ly ← lp.ly + lambdaGrid*(wd/mn - nw/mn);
        END;
    RETURN[NewObject[lp, makePXstr[nw, nl, im,nwe,nle]]];
    END;

  setPuParm: parmProc =
    BEGIN
    dp: LONG POINTER TO xstr object ← LOOPHOLE[lp.ob];
    nw, nl, wd, ln, mn,nwe,nle: INTEGER;
    nw←wd ← dp.width;
    nl←ln ← dp.length;
    nwe←dp.wExt;
    nle←dp.lExt;
    SELECT pt FROM
      width => BEGIN nw ← (wd*dy) + dx; END;
      length => BEGIN nl ← (ln*dy) + dx; END;
      default => BEGIN nl ← cLength*pRatiol; nw ← cWidth*pRatiow; END;
      wSpace => BEGIN IF -dx>dp.wExt THEN dx←-dp.wExt;nwe←dp.wExt+dx; END;
      lSpace => BEGIN IF -dx>dp.lExt THEN dx←-dp.lExt;nle←dp.lExt+dx; END;
      ENDCASE => RETURN[FALSE];
    -- new parameter ranges now tested in makePu
    IF nw = wd AND nl = ln AND dp.wExt=nwe AND dp.lExt=nle THEN RETURN[FALSE];
    mn ← 2*lambdaGrid;
    IF BITAND[lp.idx, 4] = 0 AND cent THEN
      BEGIN
      lp.lx ← lp.lx + lambdaGrid*(wd/mn - nw/mn);
      lp.ly ← lp.ly + lambdaGrid*(ln/mn - nl/mn);
      END
    ELSE
      IF cent THEN
        BEGIN
        lp.lx ← lp.lx + lambdaGrid*(ln/mn - nl/mn);
        lp.ly ← lp.ly + lambdaGrid*(wd/mn - nw/mn);
        END;
    RETURN[NewObject[lp, makePullup[nw, nl,nwe,nle]]];
    END;

  setContParm: parmProc =
    BEGIN
    dp: LONG POINTER TO cont object ← LOOPHOLE[lp.ob];
    nl, ln, mn: INTEGER;
    typ: contType ← dp.typ;
    ln ← dp.size[1];
    SELECT pt FROM
      length => BEGIN nl ← (ln*dy) + dx; END;
      default => BEGIN nl ← butconSX; END;
      ENDCASE => RETURN[FALSE];
    IF nl < butconSX THEN nl ← butconSX;
    IF nl = ln THEN RETURN[FALSE];
    mn ← 2*lambdaGrid;
    IF BITAND[lp.idx, 4] = 0 AND cent THEN
      BEGIN lp.ly ← lp.ly + lambdaGrid*(ln/mn - nl/mn); END
    ELSE IF cent THEN BEGIN lp.lx ← lp.lx + lambdaGrid*(ln/mn - nl/mn); END;
    RETURN[NewObject[lp, SELECT typ FROM
	mPol => makePolycon[nl],
	mDif => makeDifcon[nl],
	mPDif => makePDifcon[nl],
	ENDCASE => makeMmCont[nl,0,0]]];
    END;

  setBuContParm: parmProc =
    BEGIN
    dp: LONG POINTER TO cont object ← LOOPHOLE[lp.ob];
    nw, nl, wd, ln, mn,nwe,nle: INTEGER;
    nw←wd ← dp.size[0];
    nl←ln ← dp.size[1];
    nwe←dp.wExt;
    nle←dp.lExt;
    SELECT pt FROM
      width => BEGIN nw ← (wd*dy) + dx; END;
      length => BEGIN nl ← (ln*dy) + dx; END;
      default => BEGIN nl ← 8; nw ← 10;nwe←4;nle←2;END;
      wSpace => BEGIN IF -dx>dp.wExt THEN dx←-dp.wExt;
		nwe←dp.wExt+dx;nw←nw+dx*2; END;
      lSpace => BEGIN IF -dx>dp.lExt THEN dx←-dp.lExt;
		nle←dp.lExt+dx;nl←nl+dx*2; END;
      ENDCASE => RETURN[FALSE];
    IF nwe<0 THEN nwe←0;IF nle<0 THEN nle←0;
    IF nw < 2*nwe+2 THEN nw ← 2*nwe+2;
    IF nl < 2*nle+4 THEN nl ← 2*nle+4;
    IF nw = wd AND nl = ln AND dp.wExt=nwe AND dp.lExt=nle THEN RETURN[FALSE];
    mn ← 2*lambdaGrid;
    IF BITAND[lp.idx, 4] = 0 AND cent THEN
      BEGIN
      lp.lx ← lp.lx + lambdaGrid*(wd/mn - nw/mn);
      lp.ly ← lp.ly + lambdaGrid*(ln/mn - nl/mn);
      END
    ELSE
      IF cent THEN
        BEGIN
        lp.lx ← lp.lx + lambdaGrid*(ln/mn - nl/mn);
        lp.ly ← lp.ly + lambdaGrid*(wd/mn - nw/mn);
        END;
    RETURN[NewObject[lp, makeBuCont[nw, nl, nwe,nle]]];
    END;


  END.