--routeConn.mesa

DIRECTORY  RouteDefs;

RouteConn:PROGRAM IMPORTS RouteDefs EXPORTS RouteDefs=BEGIN
OPEN RouteDefs;

--The function of conn is to identify all cross channel wires,
--and create a structure containing event with start and end runs
--conn does not worry about the offset of the wire.

Error:SIGNAL=CODE;

InstallCrossChannelConnections:PUBLIC CtlProc=BEGIN
EnumerateChannels[MakeConnections];
EnumerateAllConns[CheckConnections];
--EnumerateChannels[ShowConnections];
RETURN[-1];
END;

EnumerateRunPairs:PROCEDURE[r:RectanglePtr,
   c:PROCEDURE[RectanglePtr,RunPtr,RunPtr]]=BEGIN
FOR rl:RunListPtr←r.runs,rl.t UNTIL rl=NIL DO
  FOR rl2:RunListPtr←rl.t,rl2.t UNTIL rl2=NIL
    DO c[r,rl.h,rl2.h]; ENDLOOP; ENDLOOP;
END;

MakeConnections:PROCEDURE[rect:RectanglePtr]=BEGIN
EnumerateEvents[rect,MakeEdgeConnections];
EnumerateRunPairs[rect,MakeEdgeX];
END;

MakeEdgeX:PROCEDURE[rect:RectanglePtr,r1:RunPtr,r2:RunPtr]=BEGIN
IF r1.circuit=r2.circuit AND (r1.start=r2.end OR r2.start=r1.end)
    THEN MakeInternalConnections[rect,r1,r2];
END;

MakeInternalConnections:PROCEDURE[rect:RectanglePtr,r1,r2:RunPtr]=BEGIN
seen:BOOLEAN←FALSE;
IF r1.start=r2.end THEN {t:RunPtr←r1; r1←r2; r2←t};
FOR cl:ConnListPtr←rect.conns,cl.t UNTIL cl=NIL OR seen
  DO seen←cl.h.circuit=r1.circuit AND cl.h.event=r1.end; ENDLOOP;
IF ~seen THEN QueueConn[rect,[r1.circuit,MIN[r1.run,r2.run],
         MAX[r1.run,r2.run],r1.end]];
END;

--EnumerateEventsWithAbort:PROCEDURE
--  [r:RectanglePtr,c:PROCEDURE[RectanglePtr,EventPtr] RETURNS[BOOLEAN]]=BEGIN
--FOR l:EventListPtr←rect.events, l.t UNTIL l=NIL
--  DO IF c[r,l.h] THEN RETURN; ENDLOOP;
--END;

MakeEdgeConnections:PROCEDURE[rect:RectanglePtr,e:EventPtr]=BEGIN
keyRun1,keyRun2,kk:RunPtr←NIL;
FindExtreemRun:PROCEDURE[rect:RectanglePtr,r:RunPtr]=BEGIN
  IF ~(e.circuit=r.circuit AND e.index IN [r.start..r.end]) THEN RETURN;
  IF keyRun1=NIL OR r.run<keyRun1.run THEN keyRun1←r;
  IF keyRun2=NIL OR r.run>keyRun2.run THEN keyRun2←r;
  END;
IF e.where=left OR e.where=right THEN RETURN;
IF e.opposite#NIL AND e.circuit=e.opposite.circuit THEN BEGIN
  IF e.where#top THEN RETURN;
  QueueConn[rect,[e.circuit,-1,bigRun,e.index,,,,,e]];
  e.opposite.conn←rect.conns.h;
  RETURN;
  END;
EnumerateRuns[rect,FindExtreemRun];
kk←IF e.where=top THEN keyRun1 ELSE keyRun2;
IF kk=NIL THEN RETURN;
IF e.where=top THEN QueueConn[rect,
     [e.circuit,kk.run,bigRun,e.index,,,,,e,,kk]]
               ELSE QueueConn[rect,
     [e.circuit,-1,kk.run,e.index,,,,,e,,,kk]];
IF kk.start=e.index THEN kk.startConn←rect.conns.h
    ELSE kk.endConn←rect.conns.h;
END;

QueueConn:PROCEDURE[rect:RectanglePtr,conn:Conn]=BEGIN
cp:ConnPtr=AllocateConn[];
cl:ConnListPtr=AllocateList[];
cp↑←conn;
cl↑←[cp,rect.conns];
rect.conns←cl;
IF cp.eventPtr#NIL THEN conn.eventPtr.conn←cp;
END;

GenerateRunmax:PROCEDURE[rect:RectanglePtr] RETURNS[runMax:INTEGER]=BEGIN
runMax←0;
FOR rl:RunListPtr←rect.runs,rl.t UNTIL rl=NIL
  DO runMax←MAX[runMax,rl.h.run]; ENDLOOP;
END;

CheckConnections:PROCEDURE[rect:RectanglePtr,con:ConnPtr]=BEGIN
IF con.start=-1
  THEN FOR t:EventListPtr←rect.events, t.t UNTIL t=NIL DO
      e:EventPtr←t.h;
      IF con.circuit = e.circuit AND con.event = e.index AND e.where=bottom
         THEN EXIT;
      REPEAT FINISHED=>Log[]; ENDLOOP
  ELSE FOR rl:RunListPtr←rect.runs,rl.t UNTIL rl=NIL DO
      r:RunPtr=rl.h;
      IF r.circuit=con.circuit AND r.run=con.start
       AND con.event IN [r.start..r.end] THEN EXIT;
      REPEAT FINISHED=>Log[]; ENDLOOP;
IF con.end=bigRun
  THEN FOR t:EventListPtr←rect.events, t.t UNTIL t=NIL DO
      e:EventPtr←t.h;
      IF con.circuit = e.circuit AND con.event = e.index AND e.where=top
         THEN EXIT;
      REPEAT FINISHED=>Log[]; ENDLOOP
  ELSE FOR rl:RunListPtr←rect.runs,rl.t UNTIL rl=NIL DO
      r:RunPtr=rl.h;
      IF r.circuit=con.circuit AND r.run=con.end
       AND con.event IN [r.start..r.end] THEN EXIT;
      REPEAT FINISHED=>Log[]; ENDLOOP;
END;

plowOn:BOOLEAN←FALSE;
Log:PROCEDURE={IF ~plowOn THEN Error};

ShowConnections:PROCEDURE[rect:RectanglePtr]=BEGIN
Store:PROCEDURE[c:CHARACTER,x:INTEGER]=BEGIN
  IF x NOT IN [0..line/2) THEN
    {x←x-limit+line-1; IF x NOT IN [line/2..line) THEN RETURN};
  IF c='r AND s[x]#' THEN c←'R;
  s[x]←c;
  END;
limit:CARDINAL=4+2*GenerateRunmax[rect];
line:CARDINAL=40;
limitE:CARDINAL=MAX[limit-1,line/2];
s:STRING←[line];
ShowLabel["CONNECTIONS "];
ShowDecimal[rect.channelNo];
Return[];
FOR i:INTEGER IN [0..rect.sizeC.x] DO
  SeeEvent:PROCEDURE[rect:RectanglePtr,e:EventPtr]=BEGIN
    IF i = e.index THEN BEGIN
    IF e.where=top THEN s[line-1]←ShowCircuit[e.circuit];
    IF e.where=bottom THEN s[0]←ShowCircuit[e.circuit];
    END; END;
  SeeConn:PROCEDURE[rect:RectanglePtr,con:ConnPtr]=BEGIN
    IF con.event=i THEN BEGIN
    stop:INTEGER=IF con.end=bigRun THEN limitE ELSE 2+2*con.end;
    FOR j:[0..10000) IN [2+2*con.start..stop]
      DO IF ~(j=0 OR j=limit) THEN Store['r,j]; ENDLOOP;
    END; END;
  SeeRun1:PROCEDURE[rect:RectanglePtr,r:RunPtr]=
    {IF i IN [r.start..r.end) THEN Store['b,2+2*r.run]};
  SeeRun2:PROCEDURE[rect:RectanglePtr,r:RunPtr]=
    {IF i IN [r.start..r.end) THEN Store['b,2+2*r.run]};
  Return[];
  Clear[s];
  EnumerateEvents[rect,SeeEvent];
  EnumerateConns[rect,SeeConn];
  EnumerateRuns[rect,SeeRun1];
  ShowString[s];
  Clear[s];
  EnumerateRuns[rect,SeeRun2];
  FOR zz:INTEGER IN [0..3) DO Return[]; ShowString[s]; ENDLOOP;
  ENDLOOP;
END;

END.