-- definitions module for silicon (pretty picture) program
-- last modified by McCreight, December 30, 1982  2:47 PM
-- modified by Petit, September 18, 1981  2:40 PM

DIRECTORY
  SegmentDefs,
  multiGraphicsDefs,
  StreamDefs;

ppdefs: DEFINITIONS IMPORTS SegmentDefs, multiGraphicsDefs, StreamDefs =
  BEGIN OPEN multiGraphicsDefs, StreamDefs;


  -- Note: The Chipmonk design coordinate system has x increasing to the right
  -- and y increasing downward.  [x: 0, y: 0] is the center of the design
  -- space.

  locNum: TYPE = INTEGER;
  Lambda, lambda: locNum = 2; -- 2 locNums per lambda
  Point: TYPE = RECORD [x, y: locNum];
  Rect: TYPE = RECORD [x1, y1, x2, y2: locNum];

  orientation: TYPE = [0..7]; -- multiple of 45 degrees clockwise
  reflection: TYPE = [0..1]; -- 1 means mirror in x (x ← -x)
  orientationIndex: TYPE = [0..15]; -- = 2*orientation+reflection
  -- An orientationIndex idx is composed of two parts:
  --    a clockwise rotation of (idx/2)*45 degrees,
  --    followed by a reflection in x if (idx MOD 2)#0.
  -- Odd multiples of 45 degrees are not yet supported.

  Level: TYPE = MACHINE DEPENDENT{
    cut(0), dif(1), pol(2), met(3), imp(4), ovg(5), bur(6),
    snerd(7), cut2(8), pdif(9), pwelCont(10), met2(11), pwel(12),
    nwel(13), nwelCont(14), NOcOL(15),
    l16, l17, l18, l19, l20, l21, l22, l23, l24, l25, l26, l27, l28, l29, l30, l31,
    l32, l33, l34, l35, l36, l37, l38, l39, l40, l41, l42, l43, l44, l45, l46, l47,
    l48, l49, l50, l51, l52, l53, l54, l55, l56, l57, l58, l59, l60, l61, l62, l63};
  level: TYPE = Level[cut..NOcOL];


--  I t e m   L i s t

  masterList: listPtr; -- design now being displayed
  listPtr: TYPE = LONG POINTER TO list ← NIL;
  list: TYPE = RECORD [
    nxt: listPtr,
    lx, ly: locNum,
    super: listPtr,
    ob: obPtr,
    selected, deleted, cfok, bfok, gotText: BOOLEAN ← FALSE,
    mark: [0..1] ← 0,
    idx, ridx: orientationIndex,  -- ridx is BITXOR[idx,1], i.e. reflected
    props: propPtr
    ];


--  I t e m   P r o p e r t y

  propType: TYPE = {text, interPnt, tail};
  propPtr: TYPE = LONG POINTER TO prop ← NIL;
  prop: TYPE = RECORD [
    nxt: propPtr,
    varpart: SELECT ptyp: propType FROM
      text => [s: STRING ← NIL],-- instance name
      interPnt => [pnt: listPtr],
      tail => [bpnt: listPtr],
      ENDCASE];


--  O b j e c t

  obPtr: TYPE = LONG POINTER TO object ← NIL;
  cellPtr: TYPE = LONG POINTER TO cell object ← NIL;
  object: TYPE = RECORD [
    p: POINTER TO Procs,
    size: ARRAY [0..2] OF INTEGER,
    refCnt: CARDINAL,
    auxPnt: auxPtr,
    l: level,
    surround:[0..31] ← 0,
    returnable, marked: BOOLEAN,
    varpart: SELECT otyp: typeOfObject FROM
      rect => NULL,
      wire => [super: LONG POINTER TO wire object ← NIL],
      xstr => [
        super: LONG POINTER TO xstr object ← NIL,
        width, length: INTEGER,
        wExt, lExt: [0..63],
        impl, pullup, zType, angle: BOOLEAN ← FALSE],
      cell => [
        cnt: CARDINAL,
        ptr: listPtr,
        super: cellPtr ← NIL],
      cont => [
        super: LONG POINTER TO cont object ← NIL,
        typ: contType,
        magicN,m2Ext,c2Ext: [0..15] ← 0,lExt,wExt:[0..255]←4],
      bus => [
        wspace, firstLength, topIncr, lenIncr, offsetFirst: INTEGER ← 0,
        wwidth, wCnt, tWhich,bWhich: INTEGER ← 0],
      text => [s: STRING],
      cnText => [
        s: STRING,
        np: cListPtr ← NIL,
        op: cellPtr ← NIL],
      ENDCASE];

  Procs: TYPE = RECORD [ -- generic procedures for an object
    drawme: ARRAY orientationIndex OF drProc,
    setParm: parmProc,
    inBox: ibProc,
    inMe: inMeProc,
    release: relProc,
    anotherme: anoProc];

  drProc: TYPE = PROCEDURE [
    ob: obPtr, x, y: locNum, pr: POINTER TO drRecord];
  ibProc: TYPE = PROCEDURE [lp: listPtr, x1, y1, x2, y2: locNum]
    RETURNS [BOOLEAN];
  inMeProc: TYPE = PROCEDURE [
    ob: obPtr, x, y: locNum, o: orientationIndex]
    RETURNS [BOOLEAN];
  relProc: TYPE = PROCEDURE [ob: obPtr];
  anoProc: TYPE = PROCEDURE [ob: obPtr]
    RETURNS [obPtr];
  parmProc: TYPE = PROCEDURE [
    lp: listPtr, pt: parmType, dx, dy: locNum, cent: BOOLEAN]
    RETURNS [BOOLEAN];

  aux: TYPE; -- can be implemented by any application program
  auxPtr: TYPE = LONG POINTER TO aux ← NIL;


--  N a m e d   C e l l s

  cellList: cListPtr; -- all the named cells
  cListPtr: TYPE = LONG POINTER TO cList ← NIL;
  cList: TYPE = RECORD [nxt: cListPtr, ob: obPtr, name: STRING];


--  P u s h e d  C e l l s

  cellStack: cellSEPtr; -- we are pushed down into this stack of cells
  cellSEPtr: TYPE = LONG POINTER TO cellSE ← NIL;
  cellSE: TYPE = RECORD [
    nxt: cellSEPtr,
    lp, instance, unDel: listPtr,
    dest: cellPtr,
    origSize: Point, -- of dest
    origBB: Rect, -- of instance
    cCenter: Point, -- of color screen when push happened
    cScale: INTEGER,
    changes: BOOLEAN,
    udg, udi: CARDINAL];

  UsuallyFalse: TYPE = BOOLEAN ← FALSE;
  wireOK: ARRAY level OF UsuallyFalse =
    [dif: TRUE, pol: TRUE, met: TRUE, pdif: TRUE, met2: TRUE];


  Mode: TYPE = {wire, xstr, cell, null};

  -- MAGIC CONSTANTS:

  maxInfluence: locNum = 4*Lambda;
    -- max extension of influence (or well) beyond bounding box:
  wellSurround: locNum = 4*Lambda;
  butconSY: locNum = 6*Lambda;
  butconSX: locNum = 4*Lambda;
  butconGreenOff: locNum = Lambda;
  butconRedOff: locNum = (3*Lambda)/2;

  cWidth: locNum = 2*Lambda;
  cLength: locNum = 2*Lambda;
  wXExtension: locNum = 2*Lambda;
  lXExtension: locNum = 2*Lambda;

  cut2min: locNum = 3*Lambda;
  mmContExt: locNum = 2*Lambda;-- extension of met2 beyond cut2
  --m2DifContExt: locNum = (3*Lambda)/2;- extension of met2 beyond edge of dif in a
	--	met2-met-dif contact = (cut2min + 2*mmContExt - butconSX)/2
  welconSurround: locNum = 3*Lambda;-- min well surround around a well-contact

  -- switch controlling format of color screen:
  csHor: BOOLEAN = TRUE;
  -- TRUE for long direction horizontal, FALSE for vertical;
  colWidth: INTEGER = IF csHor THEN 640 ELSE 480;
  colHeight: INTEGER = IF csHor THEN 480 ELSE 640;
  bwBottom: INTEGER = 580;
  bwMsgTop: INTEGER = bwBottom;
  bwMsgBottom: INTEGER = 640;
  bwFeedTop:INTEGER=bwMsgBottom;

  --********** command interpreter stuff:

QuitSig: SIGNAL;
RestSig: SIGNAL;
cMos: BOOLEAN;

keCheckProc:TYPE = PROCEDURE[k:keyEvent] RETURNS[return,execute:BOOLEAN];
	-- return true if command interpreter should return
	-- execute true if command interpreter should execute the keyEvent

CmdTwerp:PROCEDURE[keCheckProc] RETURNS[keyEvent];
CmdTwerpMess:PROCEDURE[os1,os2,os3:STRING,check:keCheckProc]
	RETURNS[keyEvent];


  -- kbd stuff:

  keyEvent: TYPE = RECORD [
    k: [0..77B], ctl: [0..31], mx: [0..2000], my: [0..1000]];
  nilKeyEvent: keyEvent = [k: 77B, ctl: 0, mx: 0, my: 0];

-- mx and my are the screen coordinates of the cursor when the keystroke
-- happened.  (0,0) is upper left of color screen.  (colWidth,0) is upper
-- left of B&W screen.  (colWidth,bwBottom) is upper left of feedback area.
-- ctl indicates which control keys were down, or which mouse button was
-- pushed.  k is the character key.

  --key encodings (k field of keyEvent):
  --	0-11B: "0" to "9" (add 60B for ascii)
  --	12B-43B: "A" to "Z" (add 67B for ascii upper case)
  --	44B: ";" key
  --	45B: "=" key
  --	46B: "," key
  --	47B: "-" key
  --	50B: "." key
  --	51B: "/" key
  --	52B: "'" key
  --	53B: "[" key
  --	54B: "\" key
  --	55B: "]" key
  --	56B: "DONE" key (blank one below DEL)(UNdo)
  --	57B: "←" key
  --	60B: CR key
  --	61B: LF key
  --	62B: BS key
  --	63B: DEL key
  --	64B: space bar
  --	65B: ESC
  --	66B: blank to right of RET (not used)
  --	67B: swat key (not used)
  --	70B: TAB (not used, - a ctrl key instead)
  --	71B: ???
  --	72B: ???
  --	73B: yellow mouse button up (release)
  --	74B: ???
  --	75B: ???
  --	76B: ???
  --	77B: No key (for use with mouse buttons)

  --ctrl key encodings (ctl field of keyEvent):
  --	1,2: Mouse buttons: 0-none, 1-red, 2-yellow, 3-blue
  --	4: CTRL
  --	10B: TAB
  --	20B: Shift (either)


  cursorOnBW: BOOLEAN;
  curx, cury: INTEGER;
  gridCol, gridBW: CARDINAL;

  mType: SegmentDefs.MachineType;
  color: TYPE = [0..15];

  -- ********
  bwScale: INTEGER;
  bwxoff, bwyoff: INTEGER;
  cScale: INTEGER;
  cxoff, cyoff: INTEGER;
  bwScaleN: INTEGER;
  bwScaleD: INTEGER;
  cScaleN: INTEGER;
  cScaleD: INTEGER;

  bwClipx1: INTEGER;
  bwClipx2: INTEGER;
  bwClipy1: INTEGER;
  bwClipy2: INTEGER;
  cClipx1: INTEGER;
  cClipx2: INTEGER;
  cClipy1: INTEGER;
  cClipy2: INTEGER;

  fnt: POINTER TO StrikeFont;

  typeOfObject: TYPE = {rect, wire, xstr, cell, cont, bus, text, cnText};
  contType: TYPE = {butt, mDif, mPol, burr, mm2, mPDif,
	nwell, mmDif, mmPol, mmPDif, mmButt};
  parmType: TYPE = {width, length, default, wSpace, lSpace, count, bSpace};

  cmdMask: TYPE = [0..7777B];
  -- 1=mark,2=draw,4=sel,10B=none,20B=ctrl,40B=tab,100B=ctrl-tab,
  --  200B=shift,400B=ctrl-shift,1000B=tab-shift,2000B=ctrl-tab-shift.

  cmdProc: TYPE = PROCEDURE [k: keyEvent ← nilKeyEvent];
  cmdLent: TYPE = RECORD [mask: cmdMask, proc: cmdProc];
  cmdEnt: TYPE = POINTER TO ARRAY [0..0) OF cmdLent;

  rems: TYPE = RECORD [r: Rect, l: level];
  remPages: CARDINAL = 20000/256;
  remLen: CARDINAL = (remPages*256)/SIZE[rems];

  markPnt, markDPnt, selMarkPnt: Point;

  rectListPtr: TYPE = LONG POINTER TO rectList ← NIL;
  rectList: TYPE = RECORD [
    nxt: rectListPtr, r: Rect, l: level, freebl: BOOLEAN];

  --********** screen update process stuff:

  sCmdType: TYPE = {nop, rect, sel, all};
  sCmd: TYPE = RECORD [
    cmd: sCmdType, ers: BOOLEAN, p: listPtr, r: Rect];

  drawProcer: TYPE = PROCEDURE [
    INTEGER, INTEGER, INTEGER, INTEGER, level, POINTER TO Rect];
  drawProcerc: TYPE = PROCEDURE [
    INTEGER, INTEGER, INTEGER, INTEGER, color, POINTER TO Rect];
  drawProcers: TYPE = PROCEDURE [
    INTEGER, INTEGER, INTEGER, INTEGER, STRING, POINTER TO Rect];
  drRecord: TYPE = RECORD [
    r,bigr: Rect,
    orArea, saveArea: drawProcer,
    outl: drawProcerc,
    dtxt: drawProcers,
    minSize: INTEGER];

  initRects: PROCEDURE;
  CenterAndScale: PROC [center: Point, scale: INTEGER, bw, col: BOOLEAN ← FALSE];
  reDrawRect: PROCEDURE [r: Rect, whenErase: CARDINAL, bw, col, all: BOOLEAN];
  drawNewlySel: PROCEDURE [p: listPtr];
  getColNewRect: PROCEDURE RETURNS [sCmd]; -- waits if none ready
  getBwNewRect: PROCEDURE RETURNS [sCmd]; -- waits if none ready

  --********* exports from ppspace.mesa

  swdsAloc: CARDINAL;
  lwdsAloc: LONG INTEGER;
  GetSuperPointer: PROCEDURE RETURNS [listPtr];
  GetCellSuper: PROCEDURE RETURNS [cellPtr];
  GetSpace: PROCEDURE [CARDINAL] RETURNS [LONG POINTER];
  FreeSpace: PROCEDURE [p: LONG POINTER];
  InitHeap: PROCEDURE [np: CARDINAL];
  EraseHeap: PROCEDURE;
  GetString: PROCEDURE [nchars: CARDINAL] RETURNS [s: STRING];
  FreeString: PROCEDURE [s: STRING];
  newString: PROCEDURE [s: STRING] RETURNS [ss: STRING];
  alocRectD: PROCEDURE RETURNS [p: LONG POINTER TO rect object];
  alocWireD: PROCEDURE RETURNS [p: LONG POINTER TO wire object];
  alocBusD:  PROCEDURE RETURNS [p: LONG POINTER TO bus object];
  alocXstrD: PROCEDURE RETURNS [p: LONG POINTER TO xstr object];
  alocCellD: PROCEDURE RETURNS [p: cellPtr];
  alocContD: PROCEDURE RETURNS [p: LONG POINTER TO cont object];
  alocTextD: PROCEDURE RETURNS [p: LONG POINTER TO text object];
  alocCnTextD: PROCEDURE RETURNS [p: LONG POINTER TO cnText object];
  alocList: PROCEDURE RETURNS [p: listPtr];
  alocCList: PROCEDURE RETURNS [p: cListPtr];
  freeList: PROCEDURE [listPtr];
  freeCell: PROCEDURE [p: cellPtr];

  --**** old ppprocdefs stuff:

  unDelGrpMax: CARDINAL = 10;
  unDelItemMax: CARDINAL = 300;
  unDelItemMin: CARDINAL = 30;

  unDelPnt: listPtr;
  unDelGrpCnt, unDelItemCnt: CARDINAL;

  anyChanges, sinceIOchanges: BOOLEAN;

  xRatiow: INTEGER;
  xRatiol: INTEGER;
  implant: BOOLEAN;
  pRatiow: INTEGER;
  pRatiol: INTEGER;
  pushLevel: INTEGER;

  --**** from ppprocs?:

  minWidthAr: ARRAY level OF INTEGER;

  bwGrain: INTEGER;
  colGrain: INTEGER;
  abortColor, abortBW: BOOLEAN;

  redoCBBox: PROCEDURE;

  wireList: ARRAY level OF LONG POINTER TO wire object;
  tranList: LONG POINTER TO xstr object;
  puList: LONG POINTER TO xstr object;
  contList: LONG POINTER TO cont object;
  --doColRemember:PROCEDURE ;
  --doBwRemember: PROCEDURE ;

  inrect: PROCEDURE [x, y: INTEGER, lp: listPtr] RETURNS [BOOLEAN];
  whatLevels: PROCEDURE [lp: listPtr, x, y: locNum]
    RETURNS [levs: CARDINAL];
  flushDel: PROCEDURE [lp: listPtr];

  copyObject: PROCEDURE [lp, mp: listPtr, xoff, yoff: INTEGER]
    RETURNS [np: listPtr];
  minmax: PROCEDURE [lp: listPtr]
    RETURNS [mix, miy, max, may: INTEGER];
  typeInNum: PROCEDURE [os1, os2, os3: STRING]
    RETURNS [bb: BOOLEAN, ii: INTEGER, ke: keyEvent];
  typeIn: PROCEDURE [os1, os2, os3: STRING]
    RETURNS [bb: BOOLEAN, is: STRING, ke: keyEvent];
  typeInC: PROCEDURE [os1, os2, os3: STRING] RETURNS [kk: keyEvent];
  typeOut: PROCEDURE [os1, os2, os3: STRING];
  refreshTypeInScreen: PROCEDURE ;

  initColors: PROCEDURE;
  setColors: PROCEDURE;

  getchr: PROCEDURE RETURNS [ke: keyEvent];
  getNumber: PROCEDURE RETURNS [INTEGER];
  getstr: PROCEDURE [x, y: CARDINAL] RETURNS [BOOLEAN, STRING, keyEvent];


  -- ************

  xx, yy: INTEGER;
  bb: BOOLEAN;

  moveOb: PROCEDURE [p: listPtr, x, y: INTEGER];

  mergeRects: PROCEDURE [a, b: Rect] RETURNS [Rect];
  ClipRect: PROC [a, b: Rect] RETURNS [Rect] = INLINE -- intersection
    {RETURN[[x1: MAX[a.x1, b.x1], y1: MAX[a.y1, b.y1],
      x2: MIN[a.x2, b.x2], y2: MIN[a. y2, b.y2]]]};
  Empty: PROC [r: Rect] RETURNS[BOOLEAN] = INLINE
    {RETURN[r.x2<r.x1 OR r.y2<r.y1]}; -- for directed Rects
  cannonRect: PROCEDURE [r: Rect] RETURNS [Rect];
    -- produces a non-empty Rect

  getRect: PROCEDURE [l: listPtr] RETURNS [r: Rect];


  END.