-- procedure exporting module of silicon (pretty picture) program
-- last modified by E. McCreight, February 2, 1983  3:40 PM

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

  lp: LONG POINTER TO list;
  noChange: PUBLIC BOOLEAN;
  cChange, bChange: PUBLIC BOOLEAN;
  doingAreaSel: PUBLIC BOOLEAN;

  didBW:PUBLIC BOOLEAN←FALSE;

  doMove: PUBLIC cmdProc =
    BEGIN
    dx, dy: INTEGER;
    dx ← xx - markPnt.x;
    dy ← yy - markPnt.y;
    movSel[dx, dy];
    putMark[xx, yy,FALSE];
    END;

lList:TYPE = RECORD[nxt:LONG POINTER TO lList,lp:LONG POINTER TO list,
	horz,top,bot:BOOLEAN←FALSE];

noMatches:PROCEDURE[rt:Rect,llt,ll:LONG POINTER TO lList,primary:BOOLEAN]
	RETURNS[BOOLEAN] =
    BEGIN
	rb:Rect;
	top,bot:BOOLEAN;
	rb.x2←rt.x2;
	rb.y2←rt.y2;
	IF BITAND[llt.lp.idx,4] = 0 THEN
	    BEGIN
		rb.x1←rt.x1;
		rb.y1←rt.y2;
		rt.y2←rt.y1;
	    END
	 ELSE
	    BEGIN
		rb.x1←rt.x2;
		rb.y1←rt.y1;
		rt.x2←rt.x1;
		llt.horz←TRUE;
	    END;
	WHILE ll#NIL DO
	  IF rb.x2>=ll.lp.lx AND rb.y2>=ll.lp.ly THEN
	    BEGIN
		ii:CARDINAL←IF BITAND[ll.lp.idx,4]=0 THEN 0 ELSE 1;
		top←rt.x2>=ll.lp.lx AND rt.y2>=ll.lp.ly AND
			rt.x1<=ll.lp.lx+ll.lp.ob.size[ii] AND
			rt.y1<=ll.lp.ly+ll.lp.ob.size[ii+1];
		bot←rb.x2>=ll.lp.lx AND rb.y2>=ll.lp.ly AND
			rb.x1<=ll.lp.lx+ll.lp.ob.size[ii] AND
			rb.y1<=ll.lp.ly+ll.lp.ob.size[ii+1];
		IF top OR bot THEN
		    BEGIN
			WITH ob:ll.lp.ob↑ SELECT FROM
			 cell,rect => NULL;
			 wire,bus => BEGIN
				IF ob.l#llt.lp.ob.l THEN top←bot←FALSE;
				IF NOT primary AND ll.horz=llt.horz THEN
					top←bot←FALSE;
			    END;
			 xstr => BEGIN
				IF llt.lp.ob.l=met THEN top←bot←FALSE;
			    END;
			 cont => BEGIN
				SELECT llt.lp.ob.l FROM
				dif => IF ob.typ=mPol THEN top←bot←FALSE;
				pol => IF ob.typ=mDif THEN top←bot←FALSE;
				met => IF ob.typ=burr THEN top←bot←FALSE;
				ENDCASE => top←bot←FALSE;
			    END;
			ENDCASE => top←bot←FALSE;
			llt.top←llt.top OR top;
			llt.bot←llt.bot OR bot;
		    END;
	    END;
	  ll←ll.nxt;
	ENDLOOP;
	RETURN[NOT (llt.top OR llt.bot)];
    END;
freeuplList:PROCEDURE[l:LONG POINTER TO lList] =
    BEGIN
	ll:LONG POINTER TO lList;
	WHILE l#NIL DO
	  ll←l.nxt;
	  FreeSpace[l];
	  l←ll;
	ENDLOOP;
    END;
fiddleWire:PROCEDURE[ll:LONG POINTER TO lList,dx,dy:INTEGER,primary:BOOLEAN]=
    BEGIN
	mx:INTEGER←dx;
	my:INTEGER←dy;
	r:Rect←getRect[ll.lp];
	IF ll.top THEN
	    BEGIN
		IF NOT primary THEN {IF ll.horz THEN my←0 ELSE mx←0;};
		IF NOT ll.bot THEN []←ll.lp.ob.p.setParm[ll.lp,length,
			-(IF ll.horz THEN dx ELSE dy),1,FALSE];
	    END
	 ELSE IF ll.bot THEN
	    BEGIN
		IF ll.horz THEN {mx←0;IF NOT primary THEN my←0;}
		 ELSE {my←0;IF NOT primary THEN mx←0;};
		[]←ll.lp.ob.p.setParm[ll.lp,length,
			(IF ll.horz THEN dx ELSE dy),1,FALSE];
	    END
	 ELSE RETURN;
	moveOb[ll.lp,mx,my];
	reDrawRect[r, 1, TRUE, TRUE, FALSE];
	reDrawRect[getRect[ll.lp], 0, TRUE, TRUE, FALSE];
    END;
  movSel: PROCEDURE [dx, dy: INTEGER] =
    BEGIN
    anyChanges ← sinceIOchanges ← TRUE;
    IF Stretchy THEN
      BEGIN
	ll1,ll2,ll3,ll4:LONG POINTER TO lList←NIL;
	llt,lltt:LONG POINTER TO lList;
	rt,rm:Rect;
	lp←masterList;
	WHILE lp#NIL DO
	  IF lp.selected THEN
	    BEGIN
		rt←getRect[lp];
		IF ll1=NIL THEN rm←rt
		 ELSE rm←mergeRects[rm,rt];
		llt←GetSpace[SIZE[lList]];
		llt↑←[ll1,lp];
		ll1←llt;
	    END;
	  lp ← lp.nxt;
	ENDLOOP;
	IF ll1=NIL THEN RETURN;
	lp←masterList;
	WHILE lp#NIL DO
	  IF lp.ob.otyp=wire AND NOT lp.selected THEN
	    BEGIN
		llt←GetSpace[SIZE[lList]];
		llt↑←[nxt:NIL,lp:lp];
		IF lp.lx>rm.x2 OR lp.ly>rm.y2 OR (rt←getRect[lp]).x2<rm.x1
			OR rt.y2<rm.y1 OR noMatches[rt,llt,ll1,TRUE] THEN
			{llt.nxt←ll3;ll3←llt} ELSE {llt.nxt←ll2;ll2←llt};
	    END;
	  lp ← lp.nxt;
	ENDLOOP;
	lltt←ll3;
	ll3←NIL;
	WHILE lltt#NIL DO
	  llt←lltt;
	  lltt←llt.nxt;
	  rt←getRect[llt.lp];
	  IF noMatches[rt,llt,ll2,FALSE] THEN
			{llt.nxt←ll4;ll4←llt} ELSE {llt.nxt←ll3;ll3←llt};
	ENDLOOP;
	freeuplList[ll4];
	llt←ll3;
	WHILE llt#NIL DO
	  fiddleWire[llt,dx,dy,FALSE];
	  llt←llt.nxt;
	ENDLOOP;
	llt←ll2;
	WHILE llt#NIL DO
	  fiddleWire[llt,dx,dy,TRUE];
	  llt←llt.nxt;
	ENDLOOP;
	llt←ll1;
	WHILE llt#NIL DO
	  moveOb[llt.lp,dx,dy];
	  llt←llt.nxt;
	ENDLOOP;
	freeuplList[ll3];
	freeuplList[ll2];
	freeuplList[ll1];
	RETURN;
      END;
    lp ← masterList;
    WHILE lp # NIL DO
      IF lp.selected THEN moveOb[lp, dx, dy]; lp ← lp.nxt; ENDLOOP;
    END;

  movUp: PUBLIC cmdProc = {movSel[0, -Lambda]};
  movDn: PUBLIC cmdProc = {movSel[0, Lambda]};
  movLft: PUBLIC cmdProc = {movSel[-Lambda, 0]};
  movRgt: PUBLIC cmdProc = {movSel[Lambda, 0]};

  dispErf: PUBLIC cmdProc =
    BEGIN
    x, y: INTEGER;
    st: STRING;
    b: BOOLEAN;
    i: INTEGER;
    [x, y, st, b] ← rdErfLine[];
    IF st.length = 0 THEN RETURN;
    noChange ← TRUE;
    EraseArea[200, 640, 606, 660];
    ReplaceArea[195, 641, 196, 659];
    i ← ReplaceText[st, 200, 656, fnt, normal];
    ReplaceArea[195, 641, i + 8, 642];
    ReplaceArea[195, 658, i + 8, 659];
    ReplaceArea[i + 8, 641, i + 9, 659];
    IF b THEN BEGIN cChange ← TRUE; setCoffset[x, y]; markPnt ← [x, y]; END;
    END;

  rotSel: PUBLIC cmdProc = BEGIN rotReflSel[FALSE]; END;
  rotPnt: PUBLIC cmdProc =
    BEGIN IF NOT bb THEN RETURN; rotReflPnt[FALSE, xx, yy]; END;
  mirrorSel: PUBLIC cmdProc = BEGIN rotReflSel[TRUE]; END;
  mirrorPnt: PUBLIC cmdProc = BEGIN IF bb THEN rotReflPnt[TRUE, xx, yy]; END;

  setCols: PUBLIC cmdProc = BEGIN setColors[]; dChange ← TRUE; END;

  doCopy: PUBLIC cmdProc =
    BEGIN
    dx, dy: INTEGER;
    anyChanges ← sinceIOchanges ← TRUE;
    dx ← xx - markPnt.x;
    dy ← yy - markPnt.y;
    lp ← masterList;
    WHILE lp # NIL DO
      IF lp.selected THEN
        BEGIN
        lp.selected ← FALSE;
        masterList ← copyObject[lp, masterList, dx, dy];
        masterList.selected ← TRUE;
        END;
      lp ← lp.nxt;
      ENDLOOP;
    putMark[xx, yy,FALSE];
    dChange ← TRUE;
    END;

  putMark: PUBLIC PROCEDURE [xx, yy: INTEGER, bw:BOOLEAN←FALSE] =
    BEGIN
    ww: INTEGER ← ((cScaleN + 16)*cScaleD)/cScaleN;
    qq: INTEGER ← ((bwScaleN + 15)*bwScaleD)/bwScaleN;
    x, y: INTEGER;
    [x, y] ← markPnt;
    markPnt ← [xx, yy];
    markDPnt ← [xx - x, yy - y];
    reDrawRect[[x, y, x + ww, y + ww], 1, FALSE, TRUE, FALSE];
    IF didBW THEN reDrawRect[[x, y, x + qq, y + qq], 1, TRUE, FALSE, FALSE];
    didBW←bw;
    reDrawRect[[xx, yy, xx + ww, yy + ww], 0, FALSE, TRUE, FALSE];
    IF bw THEN reDrawRect[[xx, yy, xx + qq, yy + qq], 0, TRUE, FALSE, FALSE];
    IF NOT doingAreaSel THEN selMarkPnt ← markPnt;
    END;

  setBWoffset: PUBLIC PROCEDURE [x, y: INTEGER] =
    {CenterAndScale[center: [x, y], scale: bwScale, bw: TRUE]};

  setCoffset: PUBLIC PROCEDURE [x, y: INTEGER] =
    {CenterAndScale[center: [x, y], scale: cScale, col: TRUE]};

  setBWscale: PUBLIC PROCEDURE [qq: INTEGER] =
    BEGIN
    xx, yy: INTEGER;
    [, xx, yy] ← deScaledCursor[colWidth + 303, bwBottom/2];
    CenterAndScale[center: [xx, yy], scale: qq, bw: TRUE];
    END;

  setCscale: PUBLIC PROCEDURE [qq: INTEGER] =
    BEGIN
    xx, yy: INTEGER;
    [, xx, yy] ← deScaledCursor[colWidth/2, colHeight/2];
    CenterAndScale[center: [xx, yy], scale: qq, col: TRUE];
    END;

  END.