--  keyboard interrupt routines for silicon (pretty picture) program
-- modified by McCreight, January 4, 1983  2:58 PM

DIRECTORY
  ppddefs,
  ppdddefs,ppdefs,
  multiGraphicsDefs,
  InlineDefs,
  SystemDefs;
ppccur: MONITOR IMPORTS ppdefs,ppddefs, multiGraphicsDefs,InlineDefs EXPORTS ppdddefs =
  BEGIN OPEN InlineDefs, ppdefs, ppdddefs,ppddefs, multiGraphicsDefs;

  wiring, boxing: PUBLIC BOOLEAN;
  wireCol: level;
  wireWidth: INTEGER;
  oldboxing, oldwiring, wireFlipped: BOOLEAN ← FALSE;
  oldwx, oldwy, oldbx, 	oldby,veryOldSpac,oldSpac: INTEGER;
  wirePnt, boxPnt: Point;
  wireOrn: orientation;
  tempwireOffset: INTEGER;

-- for temp busses:
  bussing: BOOLEAN←FALSE;
  wpOffx, wpOffy, cornSpac, bCnt: INTEGER;

  dx1, dy1, dx2, dy2, cx, cy: INTEGER;
  cSize: INTEGER;

  colCursPnt: POINTER TO Bitmap;
  ccOn, gotARect, ccHidden: BOOLEAN;

  initCcurse: PUBLIC PROCEDURE [size: CARDINAL, cp: POINTER TO Bitmap] =
    BEGIN
    cSize ← size;
    ccOn ← gotARect ← ccHidden ← FALSE;
    colCursPnt ← cp;
    wiring ← boxing ← FALSE;
    END;
  gonnaDoCrect: PUBLIC ENTRY PROCEDURE [x1, y1, x2, y2: INTEGER] =
    BEGIN
    dx1 ← x1;
    dy1 ← y1;
    dx2 ← x2;
    dy2 ← y2;
    gotARect ← TRUE;
    IF NOT ccOn THEN RETURN;
    IF overlap[] THEN
      BEGIN ccHidden ← TRUE; XorColorBitmap[colCursPnt, cx, cy]; END;
    END;

  doneCrect: PUBLIC ENTRY PROCEDURE =
    BEGIN
    gotARect ← FALSE;
    IF NOT ccOn THEN RETURN;
    IF ccHidden THEN XorColorBitmap[colCursPnt, cx, cy];
    ccHidden ← FALSE;
    END;

  drawColorCurs: PUBLIC ENTRY PROCEDURE [x, y: INTEGER] =
    BEGIN
    IF ccOn AND NOT ccHidden THEN XorColorBitmap[colCursPnt, cx, cy];
    cx ← x;
    cy ← y;
    IF gotARect AND overlap[] THEN ccHidden ← TRUE
    ELSE BEGIN ccHidden ← FALSE; XorColorBitmap[colCursPnt, cx, cy]; END;
    ccOn ← TRUE;
    END;

  undrawColorCurs: PUBLIC ENTRY PROCEDURE =
    BEGIN
    IF ccOn AND NOT ccHidden THEN XorColorBitmap[colCursPnt, cx, cy];
    ccOn ← FALSE;
    END;

  overlap: PROCEDURE RETURNS [BOOLEAN] =
    BEGIN
    IF cx > dx2 OR cy > dy2 OR cx + cSize < dx1 OR cy + cSize < dy1 THEN
      RETURN[FALSE];
    RETURN[TRUE];
    END;

  drawTempWire: PROCEDURE [x1, y1, x2, y2: INTEGER] =
    BEGIN
    wdt: INTEGER ← wireWidth-tempwireOffset;
    t: INTEGER;
    a, c: CARDINAL;
    IF x1 = x2 THEN
      BEGIN
      x1 ← x1 - tempwireOffset;
      x2 ← x1 + wireWidth;
      IF y1 < y2 THEN y2 ← y2 + wdt
	ELSE BEGIN t ← y1; y1 ← y2 - tempwireOffset; y2 ← t; END;
      END
    ELSE
      IF y1 = y2 THEN
        BEGIN
        y1 ← y1 - tempwireOffset;
        y2 ← y1 + wireWidth;
        IF x1 < x2 THEN x2 ← x2 + wdt
          ELSE BEGIN t ← x1; x1 ← x2 - tempwireOffset; x2 ← t; END;
        END;
    a←BITAND[orLtab[wireCol],377B];
    c←BITOR[a,BITSHIFT[a,8]];
    a←BITOR[c,4000B];
    [[x1: x1, y1: y1, x2: x2, y2: y2]] ← ClipRect[
      [x1: x1, y1: y1, x2: x2, y2: y2],
      [x1: 0, y1: 0, x2: xColorMax, y2: yColorMax]];
    IF x1<=x2 AND y1<=y2 THEN
      PutColorTemp[x1: x1, y1: y1, x2: x2, y2: y2, gray: [a, 0, c, 0, a, 0, c]];
    END;

  doTemps: PUBLIC PROCEDURE =
    BEGIN
	q,qq:INTEGER;
    IF wiring THEN
      BEGIN
      IF oldwiring AND (oldwx # curx OR oldwy # cury) THEN
        reDrawRect[getERect[], 1, FALSE, TRUE, FALSE];
      IF wireOrn = 0 OR wireOrn = 4 THEN
        BEGIN
        drawTempWire[wirePnt.x, wirePnt.y, wirePnt.x, cury];
        drawTempWire[curx, cury, wirePnt.x, cury];
	IF bussing THEN
	    BEGIN
		q←IF curx>wirePnt.x THEN cornSpac ELSE -cornSpac;
		IF cury>wirePnt.y THEN q←-q;
	        drawTempWire[wirePnt.x+wpOffx, wirePnt.y+wpOffy,
			wirePnt.x+wpOffx, cury+q];
	        drawTempWire[curx, cury+q, wirePnt.x+wpOffx, cury+q];
		q←q*bCnt;
		qq←wpOffx*bCnt;
	        drawTempWire[wirePnt.x+qq, wirePnt.y+wpOffy*bCnt,
			wirePnt.x+qq, cury+q];
	        drawTempWire[curx, cury+q, wirePnt.x+qq, cury+q];
	    END;
        END
      ELSE
        BEGIN
        drawTempWire[wirePnt.x, wirePnt.y, curx, wirePnt.y];
        drawTempWire[curx, cury, curx, wirePnt.y];
	IF bussing THEN
	    BEGIN
		q←IF cury>wirePnt.y THEN cornSpac ELSE -cornSpac;
		IF curx>wirePnt.x THEN q←-q;
	        drawTempWire[wirePnt.x+wpOffx, wirePnt.y+wpOffy,
			curx+q, wirePnt.y+wpOffy];
	        drawTempWire[curx+q, cury, curx+q, wirePnt.y+wpOffy];
		q←q*bCnt;
		qq←wpOffy*bCnt;
	        drawTempWire[wirePnt.x+wpOffx*bCnt, wirePnt.y+qq,
			curx+q, wirePnt.y+qq];
	        drawTempWire[curx+q, cury, curx+q, wirePnt.y+qq];
	    END;
        END;
      oldwx ← curx;
      oldwy ← cury;
	oldSpac←q;
	veryOldSpac←qq;
      oldwiring ← TRUE;
      END;
    IF oldwiring AND NOT wiring THEN
      BEGIN
      reDrawRect[
        cannonRect[[wirePnt.x, wirePnt.y, oldwx, oldwy]], 1, FALSE, TRUE, FALSE];
      oldwiring ← FALSE;
      END;
    IF boxing THEN
      BEGIN
      white: Color = 15;
      r: Rect = cannonRect[[x1: boxPnt.x, y1: boxPnt.y, x2: curx, y2: cury]];
      IF oldboxing AND (oldbx # curx OR oldby # cury) THEN unBox[];
      ReplaceColorArea[x1: r.x1, y1: r.y1, x2: r.x1, y2: r.y2, c: white];
      ReplaceColorArea[x1: r.x1, y1: r.y1, x2: r.x2, y2: r.y1, c: white];
      ReplaceColorArea[x1: r.x2, y1: r.y1, x2: r.x2, y2: r.y2, c: white];
      ReplaceColorArea[x1: r.x1, y1: r.y2, x2: r.x2, y2: r.y2, c: white];
      oldbx ← curx;
      oldby ← cury;
      oldboxing ← TRUE;
      END;
    IF oldboxing AND NOT boxing THEN unBox[];
    END;
  getERect: PROCEDURE RETURNS [r: Rect] =
    BEGIN
    wd: INTEGER ← wireWidth-tempwireOffset;
    two: INTEGER ← tempwireOffset;
    IF bussing THEN
		IF oldSpac<0 THEN two←two-oldSpac ELSE wd←wd+oldSpac;
    IF wireFlipped THEN
      BEGIN
      r ← cannonRect[[wirePnt.x, wirePnt.y, oldwx, oldwy]];
      r.x1 ← r.x1 - two;
      r.y1 ← r.y1 - two;
      r.x2 ← r.x2 + wd;
      r.y2 ← r.y2 + wd;
      wireFlipped ← FALSE;
      END
    ELSE
      IF wireOrn = 0 OR wireOrn = 4 THEN
        BEGIN
        r.x1 ← MIN[(IF bussing AND veryOldSpac<0 THEN wirePnt.x+veryOldSpac ELSE wirePnt.x), oldwx] - tempwireOffset;
        r.x2 ← MAX[(IF bussing AND veryOldSpac>0 THEN wirePnt.x+veryOldSpac ELSE wirePnt.x), oldwx] + wireWidth-tempwireOffset;
        IF wirePnt.y < oldwy THEN
          BEGIN
          r.y1 ← MIN[oldwy, MAX[wirePnt.y, cury]] - two;
          r.y2 ← oldwy + wd;
          END
        ELSE
          BEGIN
          r.y2 ← MAX[oldwy, MIN[wirePnt.y, cury]] + wd;
          r.y1 ← oldwy - two;
          END;
        END
      ELSE
        BEGIN
        r.y1 ← MIN[(IF bussing AND veryOldSpac<0 THEN wirePnt.y+veryOldSpac ELSE wirePnt.y), oldwy] - tempwireOffset;
        r.y2 ← MAX[(IF bussing AND veryOldSpac>0 THEN wirePnt.y+veryOldSpac ELSE wirePnt.y), oldwy] + wireWidth-tempwireOffset;
        IF wirePnt.x < oldwx THEN
          BEGIN
          r.x1 ← MIN[oldwx, MAX[wirePnt.x, curx]] - two;
          r.x2 ← oldwx + wd;
          END
        ELSE
          BEGIN
          r.x2 ← MAX[oldwx, MIN[wirePnt.x, curx]] + wd;
          r.x1 ← oldwx - two;
          END;
        END;
    [r.x1, r.y1] ← deScale[r.x1, r.y1];
    [r.x2, r.y2] ← deScale[r.x2, r.y2];
    END;
  unBox: PROCEDURE =
    BEGIN
    x1, y1, x2, y2: INTEGER;
    r: Rect;
    r ← cannonRect[[oldbx, oldby, boxPnt.x, boxPnt.y]];
    [x1, y1] ← deScale[r.x1, r.y1];
    [x2, y2] ← deScale[r.x2, r.y2];
    reDrawRect[[x1, y1, x1, y2], 1, FALSE, TRUE, FALSE];
    reDrawRect[[x1, y1, x2, y1], 1, FALSE, TRUE, FALSE];
    reDrawRect[[x2, y1, x2, y2], 1, FALSE, TRUE, FALSE];
    reDrawRect[[x1, y2, x2, y2], 1, FALSE, TRUE, FALSE];
    oldboxing ← FALSE;
    END;
  deScale: PROCEDURE [x, y: INTEGER]
    RETURNS [INTEGER, INTEGER] =
    BEGIN
    IF x > colWidth THEN x←colWidth;
    IF y > colHeight THEN y←colHeight;
    IF x < 0 THEN x←0;
    IF y < 0 THEN y←0;
    RETURN[(x*cScaleD)/cScaleN - cxoff, (y*cScaleD)/cScaleN - cyoff];
    END;

  setupTempWires: PUBLIC PROCEDURE [
    p: Point, o: orientation, col:level, wid,cornerOffset:INTEGER,
    bigChange: BOOLEAN] =
    BEGIN
    wirePnt ← p;
    IF wiring AND wireOrn # o THEN wireFlipped ← TRUE;
    IF NOT wiring THEN wireFlipped ← FALSE;
    wireOrn ← o;
    wireCol ← col;
    wireWidth ← wid;
    wiring ← TRUE;
    bussing ← FALSE;
    tempwireOffset ← cornerOffset;
    IF bigChange THEN oldwiring ← FALSE;
    END;
  setupBox: PUBLIC PROCEDURE [p: Point, bigChange: BOOLEAN] =
    BEGIN boxPnt ← p; boxing ← TRUE; IF bigChange THEN oldboxing ← FALSE; END;

  setupTempBus: PUBLIC PROCEDURE [
    p: Point, o: orientation, col:level, wid,cornerOffset:INTEGER,
    bigChange: BOOLEAN, strtOffx,strtOffy,cornerOff,count:INTEGER] =
    BEGIN
    wirePnt ← p;
    IF wiring AND wireOrn # o THEN wireFlipped ← TRUE;
    IF NOT wiring THEN wireFlipped ← FALSE;
    wireOrn ← o;
    wireCol ← col;
    wireWidth ← wid;
    wiring ← TRUE;
    bussing ← TRUE;
    tempwireOffset ← cornerOffset;
    IF bigChange THEN oldwiring ← FALSE;
    wpOffx←strtOffx;
    wpOffy←strtOffy;
    cornSpac←cornerOff;
    bCnt←count-1;
      IF wireOrn = 0 OR wireOrn = 4 THEN BEGIN IF strtOffx<0 THEN
	 cornSpac←-cornSpac;END ELSE BEGIN IF strtOffy<0 THEN
	cornSpac←-cornSpac;END;

    END;

  XorColorBitmap: PROC [source: BitmapPtr, x, y: INTEGER] = INLINE
    {SetColorFromSource[source: source, x: x, y: y, fn: invert]};

  END.