-- subroutines for command interpreter part of silicon (pretty picture) program
-- modified by E. McCreight, September 1, 1983  3:06 PM
-- modified by  Petit, September 22, 1981  5:44 PM

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

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


rotCompensate:PROCEDURE[p:listPtr] RETURNS[w,l,dw,dl:INTEGER] =
    BEGIN
	switchXY:PROCEDURE=BEGIN t:INTEGER←l;l←w;w←t;t←dl;dl←dw;dw←t;END;
	reflW:PROCEDURE=BEGIN w←p.ob.size[0]-w;dw←-dw;END;
	reflL:PROCEDURE=BEGIN l←p.ob.size[1]-l;dl←-dl;END;
	l←markPnt.y-p.ly;dl←yy-markPnt.y;
	w←markPnt.x-p.lx;dw←xx-markPnt.x;
	SELECT p.idx FROM
	0,2 => BEGIN RETURN;END;
	1,3 => BEGIN reflW[];END;
	4,6 => BEGIN switchXY[];reflL[];END;
	5,7 => BEGIN switchXY[];END;
	8,10 => BEGIN reflW[];reflL[];END;
	9,11 => BEGIN reflL[];END;
	12,14 => BEGIN switchXY[];reflW[];END;
	13,15 => BEGIN switchXY[];reflW[];reflL[];END;
	ENDCASE;
    END;
findWhichWire:PUBLIC PROCEDURE [lp:listPtr] RETURNS[wNum:INTEGER,
	onTheWire:BOOLEAN,wl1,wl2,w,l,dw,dl:INTEGER] =
    BEGIN
	ob:LONG POINTER TO bus object←LOOPHOLE[lp.ob];
	[w,l,dw,dl]←rotCompensate[lp];
	onTheWire←FALSE;
	wNum←0;
	IF lp.ob.otyp#bus THEN RETURN;
	IF w>=0 THEN
	    BEGIN
		wNum←w/ob.wspace;
		IF wNum>=ob.wCnt THEN wNum←ob.wCnt-1;
	    END;
	wl1←ob.offsetFirst+wNum*ob.topIncr;
	wl2←wl1+ob.firstLength+ob.lenIncr*wNum;
	IF w>= wNum*ob.wspace AND w<= wNum*ob.wspace+ob.wwidth
		AND l >= wl1 AND l<= wl2 THEN onTheWire←TRUE;
    END;

  convToBus: cmdProc =
    BEGIN
	makeBusCmd[k,FALSE];
    END;
  convToBusDamnit: cmdProc =
    BEGIN
	makeBusCmd[k,TRUE];
    END;

makeBusCmd:PROCEDURE[k:keyEvent,damnit:BOOLEAN] =
    BEGIN
    fstl,fstw,scnd,tp,ttp: listPtr;
    fLen,wid,spc,cnt,tinc,linc,binc,i,j,fx,fy:INTEGER;
    vert,maxok:BOOLEAN←FALSE;
    l:level;
    tp←masterList;
    cnt←0;
    WHILE tp#NIL DO
	IF tp.selected THEN
	    BEGIN
		IF tp.ob.otyp#wire THEN BEGIN tp.selected←FALSE;LOOP;END;
		cnt←cnt+1;
		IF cnt=1 THEN
		    BEGIN
			fstl←tp;
			fstw←tp;
			vert←BITAND[tp.idx,4]=0;
		    END;
		IF cnt=2 THEN scnd←tp;
		IF cnt>1 THEN
		    BEGIN
			IF vert THEN
			    BEGIN
				IF BITAND[tp.idx,4]#0 THEN RETURN;
				IF tp.lx<scnd.lx THEN scnd←tp;
				IF scnd.lx<fstw.lx THEN BEGIN ttp←fstw;
					fstw←scnd;scnd←ttp;END;
			    END
			 ELSE
			    BEGIN
				IF BITAND[tp.idx,4]=0 THEN RETURN;
				IF tp.ly<scnd.ly THEN scnd←tp;
				IF scnd.ly<fstw.ly THEN BEGIN ttp←fstw;
					fstw←scnd;scnd←ttp;END;
			    END;
		    END;
	    END;
	tp←tp.nxt;
    ENDLOOP;
    IF cnt<2 THEN RETURN;
    fLen←fstw.ob.size[1];
    wid←fstw.ob.size[0];
    linc←scnd.ob.size[1]-fLen;
    fx←fstw.lx;
    fy←fstw.ly;
    l←fstw.ob.l;
    IF vert THEN
      BEGIN
	spc←scnd.lx-fx;
	tinc←scnd.ly-fy;
	binc←scnd.ly+scnd.ob.size[1]-fLen-fy;
      END
    ELSE
      BEGIN
	spc←scnd.ly-fy;
	tinc←scnd.lx-fx;
	binc←scnd.lx+scnd.ob.size[1]-fLen-fx;
      END;
    tp←fstl;
    i←0;
    IF NOT damnit THEN
      BEGIN
    WHILE i<cnt DO
	IF tp.selected THEN
	    BEGIN
		i←i+1;
		IF tp.ob.l#l THEN RETURN;
		IF tp.ob.size[0]#wid THEN RETURN;
		IF vert THEN
		    BEGIN
			j←(tp.lx-fx)/spc;
			IF j=cnt-1 THEN maxok←TRUE;
			SELECT j FROM
			0 => IF tp#fstw THEN RETURN;
			1 => IF tp#scnd THEN RETURN;
			ENDCASE => BEGIN
				IF j*spc+fx#tp.lx THEN RETURN;
				IF j*tinc#tp.ly-fy THEN RETURN;
			    END;
		    END
		 ELSE
		    BEGIN
			j←(tp.ly-fy)/spc;
			IF j=cnt-1 THEN maxok←TRUE;
			SELECT j FROM
			0 => IF tp#fstw THEN RETURN;
			1 => IF tp#scnd THEN RETURN;
			ENDCASE => BEGIN
				IF j*spc+fy#tp.ly THEN RETURN;
				IF j*tinc#tp.lx-fx THEN RETURN;
			    END;
		    END;
		IF j*linc#tp.ob.size[1]-fLen THEN RETURN;
	    END;
	tp←tp.nxt;
    ENDLOOP;
    IF NOT maxok THEN RETURN;
      END;
    flushDelSel[]; -- delete all selected things (the wires);
    IF vert THEN BEGIN IF tinc<0 THEN fy←fy+(cnt-1)*tinc;i←tinc;j←binc;END
	ELSE BEGIN IF tinc<0 THEN fx←fx+(cnt-1)*tinc;j←-tinc;i←-binc;END;
    lp ← makeList[makeBus[fLen,wid,l,cnt,spc,i,j], fx, fy, IF vert THEN 0 ELSE 2, 0];
    masterList ← insertList[masterList, lp];
    IF createSel THEN BEGIN selNewThing[masterList, lp, TRUE]; END;
    reDrawRect[getRect[lp], 1, TRUE, TRUE, FALSE];
    END;

  modParam: cmdProc =
    BEGIN
	qqq:BOOLEAN←FALSE;
	sgn:INTEGER;
	apply:PROCEDURE[pt:parmType] =
	    BEGIN
		lp←masterList;
		WHILE lp#NIL DO
		  IF lp.selected THEN []←lp.ob.p.setParm[lp,pt,sgn,1,FALSE];
		  lp←lp.nxt;
		ENDLOOP;
	    END;
	IF k.ctl=1 THEN sgn←1 ELSE sgn←-1;
	UNTIL qqq DO
	  ke←getchr[];
	  SELECT ke.k FROM
		9 => IF ke.ctl=1 THEN sgn←1 ELSE sgn←-1;-- 9
		26 => qqq←TRUE;-- Q
		12 => apply[count];-- C
		29 => apply[lSpace];-- T
		11 => apply[bSpace];-- B
		28 => apply[wSpace];-- S
	  ENDCASE;
          reDrawRect[[0, 0, 0, 0], 2, TRUE, TRUE, TRUE];
	ENDLOOP;
    dChange ← TRUE;
    END;

  doInput: cmdProc =
    BEGIN OPEN StreamDefs;
    ss, sss: STRING ← NIL;
    IF cellStack=NIL OR HeSaysYes["You aren't at the top level so this Input"L,
      "might not have the effect you expect. Shall I press on anyway?"L] THEN
      BEGIN
      inFile: DiskHandle;
      getProc: PROC RETURNS [UNSPECIFIED] = {RETURN[inFile.get[inFile]]};
      IF (ss ← RequestString["Input file name: "L]) = NIL OR ss.length=0
        THEN GOTO FreeStrings;
      sss ← FixExtension[newString[ss], ".chip"L];
      inFile ← NewWordStream[sss, Read ! FileNameError => GOTO FreeStrings];
      fileName ← ss; ss ← NIL;
      typeOut["", "Reading File: "L, sss];
      dChange ← anyChanges ← TRUE;
      sinceIOchanges ← masterList # NIL;
      readAll[getProc];
      inFile.destroy[inFile];
      refreshTypeInScreen[];
      GOTO FreeStrings;
      EXITS FreeStrings =>
        BEGIN
        IF ss#NIL THEN FreeString[ss];
        IF sss#NIL THEN FreeString[sss];
        END;
      END;
    END;

  doOutput: cmdProc =
    BEGIN OPEN StreamDefs;
    ss: STRING ← NIL;
    savedCellStack: cellSEPtr ← cellStack;

      BEGIN ENABLE
        {Punt => GOTO FreeStrings; UNWIND => cellStack ← savedCellStack};

      outFile: DiskHandle ← NIL;
      writeInFile: PROC [w: UNSPECIFIED] = {outFile.put[outFile, w]};

      IF cellStack#NIL THEN
        BEGIN
        IF HeSaysYes["You're pushed down in a cell now.  Do you want your",
          "pushed-down state? (Y/N)"] THEN NULL
        ELSE IF HeSaysYes["We'll just write the current level as the top level",
          "design, and all the named cells as well, OK?"] THEN
          cellStack ← NIL
        ELSE GOTO FreeStrings;
        END;

      IF (ss ← RequestString["Enter File Name: "L]) = NIL OR ss.length=0
        THEN GOTO FreeStrings;
      ss ← FixExtension[ss, ".chip"];
      IF (outFile ← openOfile[ss, FALSE])=NIL AND
        NOT HeSaysYes["File Already Exists"L, ss, "OK to Overwrite? (Y/N)"L]
        THEN GOTO FreeStrings;
      outFile ← openOfile[ss, TRUE];
      typeOut["", "Writing File: "L, ss];
      writeAll[writeInFile];
      outFile.destroy[outFile];
      IF cellStack=savedCellStack THEN sinceIOchanges ← FALSE;
      refreshTypeInScreen[];
      GOTO FreeStrings;
      EXITS FreeStrings =>
        BEGIN
        cellStack ← savedCellStack;
        IF ss#NIL THEN FreeString[ss];
        END;
      END;
    END;

  makeCif: cmdProc =
    {ChipUserInt.Explain["Please use the CifGen utility instead..."]};

  defCell: cmdProc =
    BEGIN
    mix, max, miy, may: INTEGER;
    backPnt: LONG POINTER TO listPtr;
    obp: obPtr;
    ok,reDef: BOOLEAN←FALSE;
    cpp:cListPtr;
    sqs:STRING←[200];
    cob:cellPtr;

    DO
      [ok, ss, ke] ← typeIn["", "Type Cell Name:", "<CR> for none"];
      IF NOT ok THEN {refreshTypeInScreen[];RETURN;};
      IF ss.length=0 OR (cpp←FindNamedCell[ss]) = NIL THEN EXIT;
	sqs.length←0;
	AppendString[sqs,"There is already a cell named "];
	AppendString[sqs,ss];
      ke ← typeInC[sqs,"Type M to make multiple cells with same name,",
		"R to redefine old one, N to try another name"];
	IF ke.k = 26B THEN EXIT;  -- M
	IF ke.k = 33B THEN {reDef←TRUE;EXIT};  -- R
    ENDLOOP;

    selCount ← 0;
    lpp ← NIL;
    lp ← masterList;
    backPnt ← @masterList;
    WHILE lp # NIL DO
      IF lp.selected THEN
        BEGIN
        ii ← IF BITAND[lp.idx, 4] = 0 THEN 0 ELSE 1;
        IF lpp = NIL THEN
          BEGIN
          mix ← lp.lx;
          max ← lp.lx + lp.ob.size[ii];
          miy ← lp.ly;
          may ← lp.ly + lp.ob.size[ii + 1];
          END
        ELSE
          BEGIN
          mix ← MIN[mix, lp.lx];
          max ← MAX[max, lp.lx + lp.ob.size[ii]];
          miy ← MIN[miy, lp.ly];
          may ← MAX[may, lp.ly + lp.ob.size[ii + 1]];
          END;
        backPnt↑ ← lqp ← lp.nxt;
        lp.nxt ← lpp;
        lpp ← lp;
        lp ← lqp;
        END
      ELSE BEGIN backPnt ← @lp.nxt; lp ← lp.nxt; END;
      ENDLOOP;
    IF lpp # NIL THEN
      BEGIN
      anyChanges ← sinceIOchanges ← TRUE;
	IF reDef THEN
	    BEGIN
		obp←cob←LOOPHOLE[cpp.ob];
		flushDel[cob.ptr];
		cob.ptr ← lpp;
	    END
	 ELSE
	    BEGIN
		lqp ← makeList[obp ← makeCell
			[max - mix, may - miy, 0, lpp], mix, miy, 0, 0];
		masterList ← insertList[masterList, lqp];
		cob←LOOPHOLE[obp]
	    END;
      lqp ← lpp;
      WHILE lpp # NIL DO
        lpp.lx ← lpp.lx - mix;
        lpp.ly ← lpp.ly - miy;
        lpp.selected ← FALSE;
        lpp ← lpp.nxt;
        ENDLOOP;
      IF ss.length>0 AND NOT reDef THEN
        BEGIN
        cp ← alocCList[];
        cp.nxt ← cellList;
        cellList ← cp;
        cp.ob ← obp.p.anotherme[obp];
        obp.returnable ← FALSE;
        cp.name ← ss;
        END;
      dChange ← TRUE;
	IF reDef THEN
	    BEGIN
		cob.size[0] ← cob.size[2] ← max - mix;
		cob.size[1] ← may - miy;
		AdjustCallersBBoxes[cob];
	    END;
      END;
    END;

  getCell: cmdProc =
    BEGIN
    ok: BOOLEAN;
    [ok, ss, ke] ← typeIn["", "Type Cell Name:", ""];
    IF NOT ok THEN BEGIN refreshTypeInScreen[];RETURN;END;
    cp ← cellList;
    WHILE cp # NIL DO
      IF EqualString[cp.name, ss] THEN
        BEGIN
        anyChanges ← sinceIOchanges ← TRUE;
        lp ← makeList[cp.ob.p.anotherme[cp.ob], xx, yy, 0, 0];
        masterList ← insertList[masterList, lp];
        IF createSel THEN
          BEGIN selNewThing[masterList, lp, TRUE]; putMark[xx, yy]; END;
        reDrawRect[getRect[lp], 0, TRUE, TRUE, FALSE];
        refreshTypeInScreen[];
        EXIT;
        END;
      cp ← cp.nxt;
      ENDLOOP;
    FreeString[ss];
    END;

  selLayer: cmdProc =
    BEGIN
    SELECT k.k FROM
      1 =>
        BEGIN
        diffusionType ← n;
        diffusionPurpose ← wiring;
        END;
      4 =>
        BEGIN
        diffusionType ← p;
        diffusionPurpose ← wiring;
        END;
      6 =>
        BEGIN
        diffusionType ← n;
        diffusionPurpose ← wellCont;
        END;
      7 =>
        BEGIN
        diffusionType ← p;
        diffusionPurpose ← wellCont;
        END;
      ENDCASE => NULL;
    SetFavLev[(SELECT k.k FROM 1, 4, 6, 7 => dif , 2 => pol , 3 => met, 5 => met2,
      ENDCASE => unspecified)]
    END;

  makCont: cmdProc =
    BEGIN
    SELECT k.k FROM
      1 =>
        BEGIN
        lp ← makeList[makeDifcon[0], xx, yy, 0, 0];
        masterList ← insertList[masterList, lp];
        END;
      2 =>
        BEGIN
        lp ← makeList[makePolycon[0], xx, yy, 0, 0];
        masterList ← insertList[masterList, lp];
        END;
      3 =>
        BEGIN
        lp ← makeList[makeButcon[], xx, yy, basicOrientation, 0];
        masterList ← insertList[masterList, lp];
        END;
      4 =>
        BEGIN
        	lp←makeList[makeBuCont[10,8,4,2],xx,yy,basicOrientation,0];
        	masterList ← insertList[masterList, lp];
        END;
      5 =>
        BEGIN
        lp ← makeList[makeMmCont[0,4,2], xx, yy, basicOrientation, 0];
        masterList ← insertList[masterList, lp];
        END;
      6 =>
        BEGIN
        lp ← makeList[makeDifShortCont[], xx, yy, basicOrientation, 0];
        masterList ← insertList[masterList, lp];
        END;
      ENDCASE => RETURN;
    anyChanges ← sinceIOchanges ← TRUE;
    IF createSel THEN
      {selNewThing[masterList, lp, TRUE]; putMark[xx, yy]};
    reDrawRect[getRect[lp], 0, TRUE, TRUE, FALSE];
    END;

  doOvg: cmdProc =
    BEGIN
    sx, sy: INTEGER;
    ii: CARDINAL;
    IF NOT bb THEN RETURN;
    lp ← masterList;
    WHILE lp # NIL DO
      IF lp.ob.otyp = wire AND (lp.ob.l = met OR lp.ob.l=met2)
        AND lp.ob.p.inMe[lp.ob, xx - lp.lx, yy - lp.ly, lp.idx] THEN
        BEGIN
        ii ← IF BITAND[lp.idx, 4] = 0 THEN 0 ELSE 1;
        sx ← lp.ob.size[ii] - 16;
        sy ← lp.ob.size[ii + 1] - 16;
        IF sx < 1 OR sy < 1 THEN RETURN;
        lp ← makeList[makeRect[sx, sy, ovg], lp.lx + 8, lp.ly + 8, 0, 0];
        masterList ← insertList[masterList, lp];
        --		lp↑.nxt←masterList;
        --		masterList←lp;
        reDrawRect[getRect[lp], 0, TRUE, TRUE, FALSE];
        RETURN;
        END;
      lp ← lp.nxt;
      ENDLOOP;
    END;

  MakeRectangle: PROC [l: level] =
    BEGIN
    sx, sy: INTEGER;
    IF bb THEN
      BEGIN
      anyChanges ← sinceIOchanges ← TRUE;
      sx←ABS[markPnt.x-xx];sy←ABS[markPnt.y-yy];
      lp ← makeList[makeRect[sx, sy, l],
			MIN[markPnt.x,xx], MIN[markPnt.y,yy], 0, 0];
      masterList ← insertList[masterList, lp];
      IF createSel THEN
        {selNewThing[masterList, lp, TRUE]; putMark[lp.lx, lp.ly]};
      reDrawRect[getRect[lp], 0, TRUE, TRUE, FALSE];
      END;
    END;

  doTub: cmdProc = {MakeRectangle[nwel]};
  doOvgR: cmdProc = {MakeRectangle[ovg]};
  doRectangle: cmdProc = {IF rectangleMode THEN MakeRectangle[rectLev]};

  doRepeatOb: cmdProc =
    BEGIN
	lp:listPtr←masterList;
	slp:listPtr←NIL;
	ox,oy:INTEGER;
	ok: BOOLEAN;
	x,y,cnt:INTEGER;
	ke:keyEvent;
	ob:obPtr;
	mirror:BOOLEAN;
	checkMark:keCheckProc =
	    BEGIN
		return←FALSE;
		execute←(k.k=64B OR k.k=65B OR k.k=73B);
		IF (k.k=77B AND BITAND[15,k.ctl]=1) OR k.k=56B THEN
		    {return←TRUE;execute←FALSE};
	    END;
	WHILE lp#NIL DO
	  IF lp.selected THEN {IF slp#NIL THEN --error-- RETURN;slp←lp;};
	  lp←lp.nxt;
	ENDLOOP;
	IF slp=NIL THEN RETURN;
	ox←slp.lx;
	oy←slp.ly;
	ke←CmdTwerpMess["","Mark Origin of Second Copy",
			"(upper left corner)",checkMark];
	IF ke.k=56B THEN RETURN;
        [ok, x, y] ← deScaledCursor[ke.mx, ke.my];
	IF NOT ok THEN RETURN;
	x←x-ox;
	y←y-oy;
	[ok,cnt,]←typeInNum["","Type Number of Copies",""];
	IF NOT ok THEN RETURN;
	anyChanges ← sinceIOchanges ← TRUE;
	mirror←(x<0 AND y>=0) OR (x>=0 AND y<0);
	IF x<0 THEN {ox←ox+x*(cnt-1);x←-x;};
	IF y<0 THEN {oy←oy+y*(cnt-1);y←-y;};
  	ob←makeRep[slp.ob,0,0,x,y,cnt,
		(IF mirror THEN BITXOR[slp.idx,1] ELSE slp.idx)];
	slp.lx←ox;slp.ly←oy;
	slp.ob←ob;
	slp.idx←IF mirror THEN 1 ELSE 0;
	slp.ridx←BITXOR[slp.idx,1];
	reDrawRect[getRect[slp], 1, TRUE, TRUE, FALSE];
    END;

  doBurr: cmdProc =
    BEGIN
    sx, sy, dx, dy: INTEGER;
    dw, pw: listPtr ← NIL;
    di, pi: CARDINAL ← 0;
    overFlg: BOOLEAN ← FALSE;
    IF NOT bb THEN RETURN;
    lp ← masterList;
    WHILE lp # NIL DO
      IF lp.ob.otyp = wire AND lp.ob.l = pol
        AND lp.ob.p.inMe[lp.ob, xx - lp.lx, yy - lp.ly, lp.idx] THEN
        BEGIN IF pw = NIL THEN pw ← lp ELSE overFlg ← TRUE; END;
      IF lp.ob.otyp = wire AND lp.ob.l = dif
        AND lp.ob.p.inMe[lp.ob, xx - lp.lx, yy - lp.ly, lp.idx] THEN
        BEGIN IF dw = NIL THEN dw ← lp ELSE overFlg ← TRUE; END;
      lp ← lp.nxt;
      ENDLOOP;
    IF dw = NIL OR pw = NIL THEN overFlg ← TRUE;
    IF NOT overFlg THEN
      BEGIN
      di ← IF BITAND[dw.idx, 4] = 0 THEN 0 ELSE 1;
      pi ← IF BITAND[pw.idx, 4] = 0 THEN 0 ELSE 1;
      IF di = pi THEN overFlg ← TRUE
      ELSE
        BEGIN
        IF di = 0 THEN
          BEGIN
          dx ← dw.lx - 2;
          dy ← pw.ly - 2;
          sx ← dw.ob.size[0] + 4;
          sy ← pw.ob.size[0] + 6;
          IF dy > dw.ly THEN
            BEGIN
            dy ← dy - 2;
            IF dw.ly + dw.ob.size[1] > dy + 10 THEN sy ← sy + 2;
            END;
          END
        ELSE
          BEGIN
          dx ← pw.lx - 2;
          dy ← dw.ly - 2;
          sx ← pw.ob.size[0] + 6;
          sy ← dw.ob.size[0] + 4;
          IF dx > dw.lx THEN
            BEGIN
            dx ← dx - 2;
            IF dw.lx + dw.ob.size[1] > dx + 10 THEN sx ← sx + 2;
            END;
          END;
        END;
      END;
    IF overFlg THEN BEGIN dx ← xx - 4; dy ← yy - 4; sx ← sy ← 8; END;
    lp ← makeList[makeRect[sx, sy, bur], dx, dy, 0, 0];
    masterList ← insertList[masterList, lp];
    --	lp↑.nxt←masterList;
    --	masterList←lp;
    reDrawRect[getRect[lp], 0, TRUE, TRUE, FALSE];
    END;

  flushDelSel: PROCEDURE =
    BEGIN
    backPnt: LONG POINTER TO listPtr;
    lpp ← NIL;
    lp ← masterList;
    backPnt ← @masterList;
    WHILE lp # NIL DO
      IF lp.selected THEN
        BEGIN
        lp.deleted ← TRUE;
        backPnt↑ ← lqp ← lp.nxt;
        lp.nxt ← lpp;
        lpp ← lp;
        lp ← lqp;
        END
      ELSE BEGIN backPnt ← @lp.nxt; lp ← lp.nxt; END;
      ENDLOOP;
    IF lpp # NIL THEN flushDel[lpp];
    END;

  delSel: cmdProc =
    BEGIN
    backPnt: LONG POINTER TO listPtr;
    lpp ← NIL;
    lp ← masterList;
    backPnt ← @masterList;
    WHILE lp # NIL DO
      IF lp.selected=(BITAND[k.ctl, shiftKey]=0) THEN
        BEGIN
        lp.deleted ← TRUE;
        backPnt↑ ← lqp ← lp.nxt;
        lp.nxt ← lpp;
        lpp ← lp;
        lp ← lqp;
        END
      ELSE BEGIN backPnt ← @lp.nxt; lp ← lp.nxt; END;
      ENDLOOP;
    IF lpp # NIL THEN doTheDelete[lpp];
    END;

  delPnt: cmdProc =
    BEGIN
    backPnt: LONG POINTER TO listPtr;
    lpp ← NIL;
    lp ← masterList;
    backPnt ← @masterList;
    WHILE lp # NIL DO
      IF lp.ob.p.inMe[lp.ob, xx - lp.lx, yy - lp.ly, lp.idx] THEN
        BEGIN
        lp.deleted ← TRUE;
        backPnt↑ ← lqp ← lp.nxt;
        lp.nxt ← lpp;
        lpp ← lp;
        lp ← lqp;
        EXIT;
        END
      ELSE BEGIN backPnt ← @lp.nxt; lp ← lp.nxt; END;
      ENDLOOP;
    IF lpp # NIL THEN doTheDelete[lpp];
    END;

  doTheDelete: PROCEDURE [lpp: listPtr] =
    BEGIN
    jj,ii:INTEGER;
    anyChanges ← sinceIOchanges ← TRUE;
    IF (unDelGrpCnt >= unDelGrpMax AND unDelItemCnt >= unDelItemMin)
      OR unDelItemCnt >= unDelItemMax THEN flushOne[];
    jj ← 0;
    ii ← IF unDelPnt = NIL THEN 0 ELSE 1 - unDelPnt.mark;
    lp ← lpp;
    WHILE lp.nxt # NIL DO
      lp.mark ← ii;
      reDrawRect[getRect[lp], 3, TRUE, TRUE, FALSE];
      IF lp.selected THEN selCount ← selCount - 1;
      lp ← lp.nxt;
      jj ← jj + 1;
      ENDLOOP;
    reDrawRect[getRect[lp], 3, TRUE, TRUE, FALSE];
    IF lp.selected THEN selCount ← selCount - 1;
    lp.mark ← ii;
    lp.nxt ← unDelPnt;
    unDelPnt ← lpp;
    unDelGrpCnt ← unDelGrpCnt + 1;
    unDelItemCnt ← unDelItemCnt + jj + 1;
    IF unDelItemCnt >= unDelItemMax THEN flushOne[];
    END;
  flushOne: PROCEDURE =
    BEGIN
    jj:INTEGER;
    ii:CARDINAL;
    jj ← 0;
    lp ← unDelPnt;
    IF lp = NIL THEN BEGIN unDelGrpCnt ← unDelItemCnt ← 0; RETURN; END;
    FOR ii IN [2..unDelGrpCnt] DO
      WHILE lp.nxt # NIL AND lp.mark = lp.nxt.mark DO
        lp ← lp.nxt; jj ← jj + 1; ENDLOOP;
      IF ii # unDelGrpCnt AND lp.nxt # NIL THEN
        BEGIN lp ← lp.nxt; jj ← jj + 1; END;
      ENDLOOP;
    flushDel[lp.nxt];
    lp.nxt ← NIL;
    unDelGrpCnt ← unDelGrpCnt - 1;
    unDelItemCnt ← jj + 1;
    END;


  doWidenSel: cmdProc = BEGIN doParmSel[width, FALSE, TRUE, lambdaGrid, 1]; END;
  doWidenPnt: cmdProc =
    BEGIN
    IF NOT bb THEN RETURN;
    doParmPnt[width, FALSE, TRUE, lambdaGrid, 1];
    END;
  doNarwSel: cmdProc = BEGIN doParmSel[width, TRUE, FALSE, -lambdaGrid, 1]; END;
  doNarwPnt: cmdProc =
    BEGIN
    IF NOT bb THEN RETURN;
    doParmPnt[width, TRUE, FALSE, -lambdaGrid, 1];
    END;
  doDefaultSel: cmdProc = BEGIN doParmSel[default, TRUE, TRUE, 0, 0]; END;
  doDefaultPnt: cmdProc =
    BEGIN IF NOT bb THEN RETURN; doParmPnt[default, TRUE, TRUE, 0, 0]; END;
  doLenSel: cmdProc = BEGIN doParmSel[length, FALSE, TRUE, lambdaGrid, 1]; END;
  doLenPnt: cmdProc =
    BEGIN
    IF NOT bb THEN RETURN;
    doParmPnt[length, FALSE, TRUE, lambdaGrid, 1];
    END;
  doShrtSel: cmdProc =
    BEGIN
	IF wiring AND busMaking THEN
	    BEGIN
		bmNews←IF BITAND[k.ctl,20B]=0 THEN bmNews+lambdaGrid ELSE
			MAX[0,bmNews-lambdaGrid];
		setBusParms[FALSE];
		RETURN;
	    END;
	doParmSel[length, TRUE, FALSE, -lambdaGrid, 1];
    END;
  doShrtPnt: cmdProc =
    BEGIN
    IF NOT bb THEN RETURN;
    doParmPnt[length, TRUE, FALSE, -lambdaGrid, 1];
    END;

  doParmSel: PROCEDURE [
    typ: parmType, earlyRect, lateRect: BOOLEAN, dx, dy: INTEGER] =
    BEGIN
    r: Rect;
    lp ← masterList;
    WHILE lp # NIL DO
      IF lp.selected THEN
        BEGIN
        IF earlyRect THEN r ← getRect[lp];
        IF lp.ob.p.setParm[lp, typ, dx, dy, TRUE] THEN
          BEGIN
          anyChanges ← sinceIOchanges ← TRUE;
          IF lateRect THEN
            r ← (IF earlyRect THEN mergeRects[getRect[lp], r] ELSE getRect[lp]);
          reDrawRect[r, 1, TRUE, TRUE, FALSE];
          END;
        END;
      lp ← lp.nxt;
      ENDLOOP;
    END;
  doParmPnt: PROCEDURE [
    typ: parmType, earlyRect, lateRect: BOOLEAN, dx, dy: INTEGER] =
    BEGIN
    r: Rect;
    IF NOT bb THEN RETURN;
    lp ← masterList;
    WHILE lp # NIL DO
      IF lp.ob.p.inMe[lp.ob, xx - lp.lx, yy - lp.ly, lp.idx] THEN
        BEGIN
        IF earlyRect THEN r ← getRect[lp];
        IF lp.ob.p.setParm[lp, typ, dx, dy, TRUE] THEN
          BEGIN
          anyChanges ← sinceIOchanges ← TRUE;
          IF lateRect THEN
            r ← (IF earlyRect THEN mergeRects[getRect[lp], r] ELSE getRect[lp]);
          reDrawRect[r, 1, TRUE, TRUE, FALSE];
          END;
        END;
      lp ← lp.nxt;
      ENDLOOP;
    END;

  setBusParms: PROCEDURE [big: BOOLEAN] =
    BEGIN
    x, y, ww,wd,offs, sx,sy,corn: INTEGER;
    wd ← minWidthAr[wiringLev];
    ww ← (wd*cScaleN)/cScaleD;
    offs←((wd+lambdaGrid)/(2*lambdaGrid))*lambdaGrid;
    offs ← (offs*cScaleN)/cScaleD;
--    [, x, y, , ] ← cscaleRect[wclNx, wclNy, cClipx2 - 2, cClipy2 - 2];
    x←((cxoff+wclNx)*cScaleN)/cScaleD;
    y←((cyoff+wclNy)*cScaleN)/cScaleD;
    sx←(bm2dx*cScaleN)/cScaleD;
    sy←(bm2dy*cScaleN)/cScaleD;
    corn←(bmNews*cScaleN)/cScaleD;
    setupTempBus[[x,y],wiringOrn,wiringLev,ww,offs,big,sx,sy,corn,bmCount];
    END;


  END.