-- procedure exporting module of silicon (pretty picture) program
-- last modified by McCreight, December 21, 1983  10:04 AM
--   cached bitmaps added for cells
-- modified by Dillon, March 14, 1984  12:18 AM
--   to set depletionOverlap back to 1.5 lambda

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

  drText: PUBLIC drProc =
    BEGIN
    pp: LONG POINTER TO text object ← LOOPHOLE[ob];
    IF x > pr.r.x2 OR y > pr.r.y2 OR x + pp.size[0] < pr.r.x1
      OR y + pp.size[1] < pr.r.y1 THEN RETURN;
    pr.dtxt[x, y, pp.size[0], pp.size[1], pp.s, @pr.r];
    END;
  drCnText: PUBLIC drProc =
    BEGIN
    pp: LONG POINTER TO cnText object ← LOOPHOLE[ob];
    IF x > pr.r.x2 OR y > pr.r.y2 OR x + pp.size[0] < pr.r.x1
      OR y + pp.size[2] < pr.r.y1 THEN RETURN;
    drawBWText[x, y + pp.size[1], 2, 2, pp.s, NIL];
    y ← y - pp.size[2]/2 + 7;
    pr.orArea[x + 8, y, x + 14 + ob.size[0], y + 1, cut, @pr.r];
    y ← y + pp.size[2];
    pr.orArea[x + 8, y, x + 14 + ob.size[0], y + 1, cut, @pr.r];
    END;
  drRect0: PUBLIC drProc =
    BEGIN
    IF ob.l=cut OR ob.l=cut2 THEN
      pr.saveArea[x, y, x + ob.size[0], y + ob.size[1], ob.l, @pr.r]
    ELSE
      pr.orArea[x, y, x + ob.size[0], y + ob.size[1], ob.l, @pr.r];
    END;
  drRect2: PUBLIC drProc =
    BEGIN
    IF ob.l=cut OR ob.l=cut2 THEN
      pr.saveArea[x, y, x + ob.size[1], y + ob.size[0], ob.l, @pr.r]
    ELSE 
     pr.orArea[x, y, x + ob.size[1], y + ob.size[0], ob.l, @pr.r];
    END;
  drCell0: PUBLIC drProc =
    BEGIN
    pp: LONG POINTER TO cell object = LOOPHOLE[ob];
    pt: LONG POINTER TO list;
    IF x > pr.bigr.x2 OR y > pr.bigr.y2 OR x + pp.size[0] < pr.bigr.x1
      OR y + pp.size[1] < pr.bigr.y1 THEN RETURN;
    IF pp.size[0] < pr.minSize OR pp.size[1] < pr.minSize THEN
      BEGIN pr.outl[x, y, x + pp.size[0], y + pp.size[1], 12, @pr.r]; RETURN; END;
    IF pr.quickDraw#NIL AND pr.quickDraw[ob: ob, orient: 0, x: x, y: y, pr: pr].drawn THEN RETURN;
    pt ← pp.ptr;
    WHILE pt # NIL DO
      pt.ob.p.drawme[pt.idx][pt.ob, x + pt.lx, y + pt.ly, pr];
      pt ← pt.nxt;
      ENDLOOP;
    END;
  drCell2: PUBLIC drProc =
    BEGIN
    pp: LONG POINTER TO cell object = LOOPHOLE[ob];
    pt: LONG POINTER TO list;
    tt: INTEGER;
    ii: CARDINAL;
    IF x > pr.bigr.x2 OR y > pr.bigr.y2 OR x + pp.size[1] < pr.bigr.x1
      OR y + pp.size[0] < pr.bigr.y1 THEN RETURN;
    IF pp.size[0] < pr.minSize OR pp.size[1] < pr.minSize THEN
      BEGIN pr.outl[x, y, x + pp.size[1], y + pp.size[0], 12, @pr.r]; RETURN; END;
    IF pr.quickDraw#NIL AND pr.quickDraw[ob: ob, orient: 4, x: x, y: y, pr: pr].drawn THEN RETURN;
    tt ← pp.size[1] + x;
    pt ← pp.ptr;
    WHILE pt # NIL DO
      ii ← IF BITAND[pt.idx, 4] = 0 THEN 1 ELSE 2;
      pt.ob.p.drawme[
        BITAND[15, pt.idx + (IF BITAND[pt.idx, 1] = 0 THEN 4 ELSE 12)]][
        pt.ob, tt - pt.ly - pt.ob.size[ii], y + pt.lx, pr];
      pt ← pt.nxt;
      ENDLOOP;
    END;
  drCell4: PUBLIC drProc =
    BEGIN
    pp: LONG POINTER TO cell object = LOOPHOLE[ob];
    pt: LONG POINTER TO list;
    ttx, tty: INTEGER;
    ii: CARDINAL;
    IF x > pr.bigr.x2 OR y > pr.bigr.y2 OR x + pp.size[0] < pr.bigr.x1
      OR y + pp.size[1] < pr.bigr.y1 THEN RETURN;
    IF pp.size[0] < pr.minSize OR pp.size[1] < pr.minSize THEN
      BEGIN pr.outl[x, y, x + pp.size[0], y + pp.size[1], 12, @pr.r]; RETURN; END;
    IF pr.quickDraw#NIL AND pr.quickDraw[ob: ob, orient: 8, x: x, y: y, pr: pr].drawn THEN RETURN;
    ttx ← x + pp.size[0];
    tty ← y + pp.size[1];
    pt ← pp.ptr;
    WHILE pt # NIL DO
      ii ← IF BITAND[pt.idx, 4] = 0 THEN 0 ELSE 1;
      pt.ob.p.drawme[BITAND[15, pt.idx + 8]][
        pt.ob, ttx - pt.ob.size[ii] - pt.lx, tty - pt.ob.size[ii + 1] - pt.ly,
        pr];
      pt ← pt.nxt;
      ENDLOOP;
    END;
  drCell6: PUBLIC drProc =
    BEGIN
    pp: LONG POINTER TO cell object = LOOPHOLE[ob];
    pt: LONG POINTER TO list;
    tt: INTEGER;
    ii: CARDINAL;
    IF x > pr.bigr.x2 OR y > pr.bigr.y2 OR x + pp.size[1] < pr.bigr.x1
      OR y + pp.size[0] < pr.bigr.y1 THEN RETURN;
    IF pp.size[0] < pr.minSize OR pp.size[1] < pr.minSize THEN
      BEGIN pr.outl[x, y, x + pp.size[1], y + pp.size[0], 12, @pr.r]; RETURN; END;
    IF pr.quickDraw#NIL AND pr.quickDraw[ob: ob, orient: 12, x: x, y: y, pr: pr].drawn THEN RETURN;
    tt ← y + pp.size[0];
    pt ← pp.ptr;
    WHILE pt # NIL DO
      ii ← IF BITAND[pt.idx, 4] = 0 THEN 0 ELSE 1;
      pt.ob.p.drawme[
        BITAND[15, pt.idx + (IF BITAND[pt.idx, 1] = 0 THEN 12 ELSE 4)]][
        pt.ob, x + pt.ly, tt - pt.ob.size[ii] - pt.lx, pr];
      pt ← pt.nxt;
      ENDLOOP;
    END;
  drCell0R: PUBLIC drProc =
    BEGIN
    pp: LONG POINTER TO cell object = LOOPHOLE[ob];
    pt: LONG POINTER TO list;
    tt: INTEGER;
    ii: CARDINAL;
    IF x > pr.bigr.x2 OR y > pr.bigr.y2 OR x + pp.size[0] < pr.bigr.x1
      OR y + pp.size[1] < pr.bigr.y1 THEN RETURN;
    IF pp.size[0] < pr.minSize OR pp.size[1] < pr.minSize THEN
      BEGIN pr.outl[x, y, x + pp.size[0], y + pp.size[1], 12, @pr.r]; RETURN; END;
    IF pr.quickDraw#NIL AND pr.quickDraw[ob: ob, orient: 1, x: x, y: y, pr: pr].drawn THEN RETURN;
    pt ← pp.ptr;
    tt ← pp.size[0] + x;
    WHILE pt # NIL DO
      ii ← IF BITAND[pt.idx, 4] = 0 THEN 0 ELSE 1;
      pt.ob.p.drawme[pt.ridx][pt.ob, tt - pt.ob.size[ii] - pt.lx, y + pt.ly, pr];
      pt ← pt.nxt;
      ENDLOOP;
    END;
  drCell2R: PUBLIC drProc =
    BEGIN
    pp: LONG POINTER TO cell object = LOOPHOLE[ob];
    pt: LONG POINTER TO list;
    IF x > pr.bigr.x2 OR y > pr.bigr.y2 OR x + pp.size[1] < pr.bigr.x1
      OR y + pp.size[0] < pr.bigr.y1 THEN RETURN;
    IF pp.size[0] < pr.minSize OR pp.size[1] < pr.minSize THEN
      BEGIN pr.outl[x, y, x + pp.size[1], y + pp.size[0], 12, @pr.r]; RETURN; END;
    IF pr.quickDraw#NIL AND pr.quickDraw[ob: ob, orient: 5, x: x, y: y, pr: pr].drawn THEN RETURN;
    pt ← pp.ptr;
    WHILE pt # NIL DO
      pt.ob.p.drawme[
        BITAND[15, pt.ridx + (IF BITAND[pt.idx, 1] = 0 THEN 4 ELSE 12)]][
        pt.ob, x + pt.ly, y + pt.lx, pr];
      pt ← pt.nxt;
      ENDLOOP;
    END;
  drCell4R: PUBLIC drProc =
    BEGIN
    pp: LONG POINTER TO cell object = LOOPHOLE[ob];
    pt: LONG POINTER TO list;
    tty: INTEGER;
    ii: CARDINAL;
    IF x > pr.bigr.x2 OR y > pr.bigr.y2 OR x + pp.size[0] < pr.bigr.x1
      OR y + pp.size[1] < pr.bigr.y1 THEN RETURN;
    IF pp.size[0] < pr.minSize OR pp.size[1] < pr.minSize THEN
      BEGIN pr.outl[x, y, x + pp.size[0], y + pp.size[1], 12, @pr.r]; RETURN; END;
    IF pr.quickDraw#NIL AND pr.quickDraw[ob: ob, orient: 9, x: x, y: y, pr: pr].drawn THEN RETURN;
    tty ← y + pp.size[1];
    pt ← pp.ptr;
    WHILE pt # NIL DO
      ii ← IF BITAND[pt.idx, 4] = 0 THEN 1 ELSE 2;
      pt.ob.p.drawme[BITAND[15, pt.ridx + 8]][
        pt.ob, x + pt.lx, tty - pt.ob.size[ii] - pt.ly, pr];
      pt ← pt.nxt;
      ENDLOOP;
    END;
  drCell6R: PUBLIC drProc =
    BEGIN
    pp: LONG POINTER TO cell object = LOOPHOLE[ob];
    pt: LONG POINTER TO list;
    ttx, tty: INTEGER;
    ii: CARDINAL;
    IF x > pr.bigr.x2 OR y > pr.bigr.y2 OR x + pp.size[1] < pr.bigr.x1
      OR y + pp.size[0] < pr.bigr.y1 THEN RETURN;
    IF pp.size[0] < pr.minSize OR pp.size[1] < pr.minSize THEN
      BEGIN pr.outl[x, y, x + pp.size[1], y + pp.size[0], 12, @pr.r]; RETURN; END;
    IF pr.quickDraw#NIL AND pr.quickDraw[ob: ob, orient: 13, x: x, y: y, pr: pr].drawn THEN RETURN;
    ttx ← x + pp.size[1];
    tty ← y + pp.size[0];
    pt ← pp.ptr;
    WHILE pt # NIL DO
      ii ← IF BITAND[pt.idx, 4] = 0 THEN 0 ELSE 1;
      pt.ob.p.drawme[
        BITAND[15, pt.ridx + (IF BITAND[pt.idx, 1] = 0 THEN 12 ELSE 4)]][
        pt.ob, ttx - pt.ob.size[ii + 1] - pt.ly, tty - pt.ob.size[ii] - pt.lx,
        pr];
      pt ← pt.nxt;
      ENDLOOP;
    END;

  depletionOverlap: locNum = (3*Lambda)/2;

  drXstr0: PUBLIC drProc =
    BEGIN
    p: LONG POINTER TO xstr object = LOOPHOLE[ob];
    IF x-p.surround > pr.r.x2 OR y-p.surround > pr.r.y2
      OR x + p.size[0]+p.surround < pr.r.x1
      OR y + p.size[1]+p.surround < pr.r.y1 THEN RETURN;
    pr.orArea[x + p.wExt, y, x + p.width + p.wExt, y + p.size[1], p.l, @pr.r];
    pr.orArea[x, y + p.lExt, x + p.size[0], y + p.length + p.lExt, pol, @pr.r];
    IF p.impl#enhancement THEN
      pr.orArea[x+p.wExt-depletionOverlap, y+p.lExt-depletionOverlap,
        x + p.size[0]-p.wExt+depletionOverlap, y + p.size[1]-p.lExt+depletionOverlap,
        imp, @pr.r];
    IF p.l=pdif THEN
      pr.orArea[x-p.surround+p.wExt, y-p.surround, x + p.size[0]+p.surround-p.wExt,
      y + p.size[1]+p.surround, nwel, @pr.r];
    END;

  drXstr2: PUBLIC drProc =
    BEGIN
    p: LONG POINTER TO xstr object = LOOPHOLE[ob];
    IF x-p.surround > pr.r.x2 OR y-p.surround > pr.r.y2
      OR x + p.size[1]+p.surround < pr.r.x1
      OR y + p.size[0]+p.surround < pr.r.y1 THEN RETURN;
    pr.orArea[x, y + p.wExt, x + p.size[1], y + p.width + p.wExt, p.l, @pr.r];
    pr.orArea[x + p.lExt, y, x + p.length + p.lExt, y + p.size[0], pol, @pr.r];
    IF p.impl#enhancement THEN
      pr.orArea[x+p.lExt-depletionOverlap, y+p.wExt-depletionOverlap,
        x + p.size[1]-p.lExt+depletionOverlap, y + p.size[0]-p.wExt+depletionOverlap,
        imp, @pr.r];
    IF p.l=pdif THEN
      pr.orArea[x-p.surround, y-p.surround+p.wExt, x + p.size[1]+p.surround,
      y + p.size[0]+p.surround-p.wExt, nwel, @pr.r];

    END;

  drAXstr0: PUBLIC drProc =
    BEGIN
    p: LONG POINTER TO xstr object = LOOPHOLE[ob];
    ele: locNum;
    hPoly, vPoly, nDrain, eDrain, wSource, sSource: Rect;
    IF x-p.surround > pr.r.x2 OR y-p.surround > pr.r.y2
      OR x + p.size[0]+p.surround < pr.r.x1
      OR y + p.size[1]+p.surround < pr.r.y1 THEN RETURN;

    ele ← 2*p.lExt+p.length; -- length and two length extensions

    -- The transistor makes a 90-degree bend, going eastward and
    -- then southward.  The diffusion on the outer side of the angle,
    -- that is, on the northeast side, is arbitrarily called the drain.

    hPoly ← [x1: x, y1: y+p.lExt,
      x2: x+p.size[0]-p.lExt, y2: y+p.length+p.lExt];
    vPoly ← [x1: x+p.size[0]-p.length-p.lExt,
      y1: hPoly.y2, x2: hPoly.x2, y2: y+p.size[1]];
    nDrain ← [x1: x+p.wExt, y1: y, x2: x+p.size[0],
      y2: hPoly.y1];
    eDrain ← [x1: vPoly.x2, y1: nDrain.y2,
      x2: nDrain.x2, y2: y+p.size[1]-p.wExt];
    wSource ← [
      x1: x+p.size[0]-ele,
      y1: eDrain.y1,
      x2: eDrain.x1,
      y2: y+p.size[1]-p.wExt];
    sSource ← [x1: x+MIN[p.wExt, p.size[0]-ele],
      y1: nDrain.y2,
      x2: wSource.x1,
      y2: y+MIN[ele, p.size[1]-p.wExt]];

    IF p.lExt>0 THEN
      BEGIN
      pr.orArea[nDrain.x1, nDrain.y1, nDrain.x2, nDrain.y2,
        p.l, @pr.r]; -- north "drain" dif
      pr.orArea[eDrain.x1, eDrain.y1, eDrain.x2, eDrain.y2,
        p.l, @pr.r]; -- east "drain" dif
      END;
    pr.orArea[wSource.x1, wSource.y1, wSource.x2, wSource.y2,
      p.l, @pr.r]; -- west "source" dif
    pr.orArea[sSource.x1, sSource.y1, sSource.x2, sSource.y2,
      p.l,@pr.r];  -- south "source" dif

    pr.orArea[hPoly.x1, hPoly.y1, hPoly.x2, hPoly.y2, pol, @pr.r];
      -- horizontal gate
    pr.orArea[vPoly.x1, vPoly.y1, vPoly.x2, vPoly.y2, pol, @pr.r];
      -- vertical gate

    IF p.impl#enhancement THEN
      BEGIN
      pr.orArea[nDrain.x1-depletionOverlap, hPoly.y1-depletionOverlap,
        hPoly.x2+depletionOverlap, hPoly.y2+depletionOverlap,
        imp, @pr.r];
      pr.orArea[vPoly.x1-depletionOverlap, vPoly.y1-depletionOverlap,
        vPoly.x2+depletionOverlap, eDrain.y2+depletionOverlap,
        imp, @pr.r];
      END;
    IF p.l=pdif THEN
      pr.orArea[x-p.surround+p.wExt, y-p.surround, x + p.size[0]+p.surround-p.wExt,
      y + p.size[1]+p.surround, nwel, @pr.r];
    END;

  drArb: PUBLIC PROCEDURE[dr0: drProc, orient: orientationIndex,
    ob: obPtr, x, y: locNum, pr: POINTER TO drRecord] =
    BEGIN OPEN ChipOrient;

    arbOrArea: PROCEDURE[x1, y1, x2, y2: locNum, l: level,
      p: POINTER TO Rect] =
      BEGIN
      IF x1<x2 AND y1<y2 THEN
        BEGIN
        r: Rect ← MapRect[
          itemInCell: [x1: x1, y1: y1, x2: x2, y2: y2],
          cellInstOrient: orient,
          cellSize: [x: ob.size[0], y: ob.size[1]],
          cellInstPos: [x: x, y: y]
          ];
        pr.orArea[r.x1, r.y1, r.x2, r.y2, l, @pr.r];
        END;
      END; -- of arbOrArea

    arbSaveArea: PROCEDURE[x1, y1, x2, y2: locNum, l: level,
      p: POINTER TO Rect] =
      BEGIN
      IF x1<x2 AND y1<y2 THEN
        BEGIN
        r: Rect ← MapRect[
          itemInCell: [x1: x1, y1: y1, x2: x2, y2: y2],
          cellInstOrient: orient,
          cellSize: [x: ob.size[0], y: ob.size[1]],
          cellInstPos: [x: x, y: y]
          ];
        pr.saveArea[r.x1, r.y1, r.x2, r.y2, l, @pr.r];
        END;
      END; -- of arbSaveArea

    OrientBoundary: PROCEDURE[bdry: Rect] RETURNS[Rect] =
      BEGIN
      -- We have a problem of integer overflow here if
      -- bdry is the universe (or near it).

      universe: Rect = [x1: -LAST[locNum], y1: -LAST[locNum],
        x2: LAST[locNum], y2: LAST[locNum]];
      RETURN[IF bdry=universe THEN universe
        ELSE DeMapRect[
          itemInWorld: bdry,
          cellSize: [x: ob.size[0], y: ob.size[1]],
          cellInstOrient: orient,
          cellInstPos: [x: x, y: y]]];
      END;

    arbDr: drRecord ← [
      r: OrientBoundary[pr.r],
      bigr: OrientBoundary[pr.bigr],
      orArea: arbOrArea,
      saveArea: arbSaveArea,
      outl: NIL,
      dtxt: NIL,
      minSize: pr.minSize
      ];
    dr0[ob, 0, 0, @arbDr];
    END; -- of drArb


  drAXstrR0: PUBLIC drProc =
    {drArb[drAXstr0, 1, ob, x, y, pr]};

  drAXstr2: PUBLIC drProc =
    {drArb[drAXstr0, 4, ob, x, y, pr]};

  drAXstrR2: PUBLIC drProc =
    {drArb[drAXstr0, 5, ob, x, y, pr]};

  drAXstr4: PUBLIC drProc =
    {drArb[drAXstr0, 8, ob, x, y, pr]};

  drAXstrR4: PUBLIC drProc =
    {drArb[drAXstr0, 9, ob, x, y, pr]};

  drAXstr6: PUBLIC drProc =
    {drArb[drAXstr0, 12, ob, x, y, pr]};

  drAXstrR6: PUBLIC drProc =
    {drArb[drAXstr0, 13, ob, x, y, pr]};



  END.