-- variables for command interpreter part of silicon (pretty picture) program
-- created by  Petit, September 23, 1981  3:44 PM
-- last modified by McCreight, October 17, 1982  3:48 PM

DIRECTORY
  InlineDefs,
  StringDefs,
  ppoutdefs,
  ppdddefs,ppddefs,
  ppdefs,
  ppMainDefs;

ppmain3: PROGRAM IMPORTS
    ppdddefs, ppdefs, ppddefs, ppMainDefs, InlineDefs
  EXPORTS ppMainDefs,ppddefs = PUBLIC
  BEGIN
  OPEN ppdefs, ppddefs, ppdddefs,ppoutdefs, StringDefs, InlineDefs,
    ppMainDefs;

busMaking:BOOLEAN←FALSE;
bmCount,bm2dx,bm2dy,bmNews:INTEGER;

  minSpaceAr:ARRAY[0..7] OF INTEGER = [2,6,4,6,2,2,2,2];

  wClosestDisp: BOOLEAN ← FALSE;
  wirePrevPnt: LONG POINTER TO list;
  wiringLev: level;
  wiringOrnSet: BOOLEAN ← FALSE;
  moving: BOOLEAN ← FALSE;
  copying: BOOLEAN ← FALSE;
  areaSel: BOOLEAN ← FALSE;
  moveMarked: BOOLEAN ← FALSE;

  markx, marky: INTEGER;

  wclLp: LONG POINTER TO list;
  wclNx, wclNy, oldNx, oldNy: INTEGER;
  currentLevel: level ← cut;
  curcol: INTEGER ← 0;

  insertList: PROCEDURE [mp, lp: LONG POINTER TO list]
    RETURNS [LONG POINTER TO list] = BEGIN lp↑.nxt ← mp; RETURN[lp]; END;

  doAlter: cmdProc =
    BEGIN
	found,top:BOOLEAN←FALSE;
	l,w,dl,dw,wNum,wl1,wl2:INTEGER;
	pt:parmType;
	r: Rect;
	IF NOT bb THEN RETURN;
	FOR lp: listPtr ← masterList, lp.nxt WHILE  lp # NIL DO
	  IF NOT lp.selected OR
	    NOT lp.ob.p.inMe[lp.ob, markPnt.x - lp.lx, markPnt.y - lp.ly, lp.idx]
	    THEN LOOP;
	  SELECT lp.ob.otyp FROM
	    cont, xstr =>
	    BEGIN
		IF lp.ob.otyp=cont AND
		    (LOOPHOLE[lp.ob,LONG POINTER TO cont object].typ)#burr
			THEN LOOP;
		found←TRUE;
		IF BITAND[lp.idx,4]=0 THEN
		    BEGIN
			l←markPnt.y-lp.ly;dl←yy-markPnt.y;
			w←markPnt.x-lp.lx;dw←xx-markPnt.x;
		    END
		 ELSE
		    BEGIN
			w←markPnt.y-lp.ly;dw←yy-markPnt.y;
			l←markPnt.x-lp.lx;dl←xx-markPnt.x;
		    END;
		IF l>1 THEN BEGIN l←lp.ob.size[1]-l;dl←-dl;END;
		IF w>1 THEN BEGIN w←lp.ob.size[0]-w;dw←-dw;END;
		IF (l>1 AND w>1) OR l=w THEN RETURN;
		IF l<w THEN
		    BEGIN
			pt←lSpace;
		    END
		 ELSE
		    BEGIN
			pt←wSpace;
			dl←dw;
		    END;
		dl←-dl;
		EXIT;
	    END;
	    bus =>
	    BEGIN
		dNum,do:INTEGER;
		ob:LONG POINTER TO bus object;
		[wNum,found,wl1,wl2,w,l,dw,dl]←findWhichWire[lp];
		IF NOT found THEN LOOP;
		anyChanges ← sinceIOchanges ← TRUE;
		top←l-wl1 <= wl2-l;
		ob←LOOPHOLE[lp.ob];
		r←getRect[lp];
		IF dl=0 THEN
		    BEGIN -- peg that wire in place
			IF top THEN ob.tWhich←wNum ELSE ob.bWhich←wNum;
			RETURN;
		    END;
		dNum←IF top THEN ob.tWhich ELSE ob.bWhich;
		IF wNum=dNum THEN
		    BEGIN
			IF top THEN do←-dl
			 ELSE do←dl;
			ob.firstLength←ob.firstLength+do;
			IF ob.firstLength<=0 THEN ob.firstLength←1;
		    END
		 ELSE
		    BEGIN
			do←IF dl>=0 THEN (dl+ABS[dNum-wNum]-1)/(wNum-dNum)
				ELSE (dl-ABS[dNum-wNum]+1)/(wNum-dNum);
			IF top THEN
			    BEGIN
				ob.topIncr←ob.topIncr+do;
				ob.lenIncr←ob.lenIncr-do;
				ob.firstLength←ob.firstLength+do*dNum;
			    END
			 ELSE
			    BEGIN
				ob.lenIncr←ob.lenIncr+do;
				ob.firstLength←ob.firstLength-do*dNum;
			    END;
		    END;
		wl1←ob.lenIncr+ob.topIncr;--binc
		ob.offsetFirst ← IF ob.topIncr>=0 THEN 0 ELSE
		   (1-ob.wCnt)*ob.topIncr;
		l←IF wl1>0 THEN ob.offsetFirst+ob.firstLength+(ob.wCnt-1)*wl1
		  ELSE ob.offsetFirst+ob.firstLength;
		dl←ob.size[1]-l;
		ob.size[1]←l;
		SELECT lp.idx FROM
		0,1,2,3 => BEGIN IF top THEN lp.ly←lp.ly+dl;END;
		4,6,13,15 => BEGIN IF NOT top THEN lp.lx←lp.lx+dl;END;
		5,7,12,14 => BEGIN IF top THEN lp.lx←lp.lx+dl;END;
		8,9,10,11 => BEGIN IF NOT top THEN lp.ly←lp.ly+dl;END;
		ENDCASE;
		r ← mergeRects[getRect[lp], r];
		reDrawRect[r, 1, TRUE, TRUE, FALSE];
		RETURN;
	    END;
	    ENDCASE => NULL;
	ENDLOOP;
	IF NOT found THEN RETURN;

    FOR lp: listPtr ← masterList, lp.nxt WHILE  lp # NIL DO
      IF lp.selected AND (lp.ob.otyp = xstr OR lp.ob.otyp=cont) THEN
        BEGIN
        r ← getRect[lp];
        IF lp.ob.p.setParm[lp, pt, dl, 1, TRUE] THEN
          BEGIN
          anyChanges ← sinceIOchanges ← TRUE;
          r ← mergeRects[getRect[lp], r];
          reDrawRect[r, 1, TRUE, TRUE, FALSE];
          END;
        END;
      ENDLOOP;
    IF NOT wiring THEN putMark[xx, yy];
    END;

  doWAlter: cmdProc =
    BEGIN
	wNum,dNum,wl1,wl2,l,w,dl,dw,do:INTEGER;
	r: Rect;
	top,found:BOOLEAN;
	IF NOT bb THEN RETURN;
	FOR lp: listPtr ← masterList, lp.nxt WHILE lp # NIL DO
	  IF NOT lp.selected OR
	    NOT lp.ob.p.inMe[lp.ob,markPnt.x-lp.lx, markPnt.y - lp.ly, lp.idx]
	    THEN LOOP;
	  WITH ob: lp.ob SELECT FROM
	    bus =>
	    BEGIN
		[wNum,found,wl1,wl2,w,l,dw,dl]←findWhichWire[lp];
		IF NOT found THEN LOOP;
		anyChanges ← sinceIOchanges ← TRUE;
		top←l-wl1 <= wl2-l;
		r←getRect[lp];
		dNum←IF top THEN ob.tWhich ELSE ob.bWhich;
		IF wNum=dNum THEN RETURN;
		do←IF dw>=0 THEN (dw+ABS[dNum-wNum]-1)/(wNum-dNum)
				ELSE (dw-ABS[dNum-wNum]+1)/(wNum-dNum);
		l←ob.wspace+do;
		IF l<=0 THEN l←1;
		dl←l-ob.wspace;
		ob.wspace←l;
		ob.size[0]←ob.size[2]←(ob.wCnt-1)*l+ob.wwidth;
		SELECT lp.idx FROM
		0,2,9,11 => BEGIN lp.lx←lp.lx-dl*dNum;END;
		1,3,8,10 => BEGIN lp.lx←lp.lx-dl*(ob.wCnt-dNum-1);END;
		4,5,6,7 => BEGIN lp.ly←lp.ly-dl*dNum;END;
		12,13,14,15 => BEGIN lp.ly←lp.ly-dl*(ob.wCnt-dNum-1);END;
		ENDCASE;
		r ← mergeRects[getRect[lp], r];
		reDrawRect[r, 1, TRUE, TRUE, FALSE];
		RETURN;
	    END;
--	    wire =>
--	    BEGIN
--	    END;
	    ENDCASE => NULL;
	ENDLOOP;
    END;

  doImplSel: cmdProc =
    BEGIN
	IF wiring AND busMaking THEN
	    BEGIN
		bmCount←bmCount+1;
		setBusParms[FALSE];
		RETURN;
	    END;
        doParmSel[count, FALSE, TRUE, 1, 1];
    END;
  doUnImplSel: cmdProc =
    BEGIN
	IF wiring AND busMaking THEN
	    BEGIN
		bmCount←MAX[1,bmCount-1];
		setBusParms[FALSE];
		RETURN;
	    END;
        doParmSel[count, TRUE, FALSE, -1, 1];
    END;
  doImplPnt: cmdProc =
    BEGIN
    IF NOT bb THEN RETURN;
    doParmPnt[count, TRUE, TRUE, (IF BITAND[k.ctl,20B]=0 THEN 1 ELSE -1), 1];
    END;

  END.