@X @~
~L3 COUK1247
80
~V7 56 2 -5
~D10
~H                    MUSS
~
~
~D10
~H             DOC041
~D10
~MMANCHESTER UNIVERSITY  -  CONFIDENTIAL
~
~
                                                             ISSUE 11~
~V9 -1
~P
~V9 1
~YDOC041
~S1~M~ODOCUMENTATION IMPLEMENTATION DESCRIPTION
~S1~M~OSection 4 Version 1
~S1~OSection 4.1 Batch Flowchart Drawing
~S1~O1. General Description
~BThis section consists of two main procedures, DRAW which is
the batch drawing facility and DRAW.CHART which is called by
DRAW and performs the main functions in creating the chart. DRAW
calls INPUT.TITLE and INPUT.CHART in section 2 to form a
tabular representation of the chart and DRAW.CHART analyses this to
produce a set of procedure calls.
These calls drive either an ordinary lineprinter or any of a
number of graphics devices which are controlled via the CORE
graphics library or a suitable subet.  The format of the procedure
calls is device independent.
~S1~O2. Interfaces
~
~OOther Modules~O~
  DOC021~
  DOC051~
  DOC061~
  DOC071~
  DOC091~
~
~OProcedures~O~
  DRAW~
  DRAW.CHART~
~
~OTypes~O~
  DATA~
  OUTCOM~
~
~OData Structures~O~
  COLX~
  DATESTR~
  TBUFF~
  MAXX~
  MINY~
  XMAP~
  XSCALE~
  XD~
  XPOS~
  YMAP~
  YSCALE~
  YD~
  YPOS~
  PHGT~
  OCT~
  OCTPTR~
  PICPTR~
  SPCT~
~OLiterals~O~
  HWR~
  MINX~
  MAXY~
~S1~O2.1 Hardware Interface
~BNone.
~S1~O2.2 Software Interface
~
~
1) DRAW(INPUT.FILE,OUTPUT.FILE,TRANSLATION.LEVELS,~
         OUTPUT.DEVICE.TYPE)~
~BThis is a library procedure which draws charts from specifications
on the INPUT.FILE, onto the specified OUTPUT.FILE in a form suitable for the
specified OUTPUT.DEVICE.TYPE (lineprinteror graphics device) at the
specified TRANSLATION.LEVELS. A list of titles of the charts to be
drawn should follow the call for this procedure, seperated by newlines
and terminated by '@' (at the start of a line). The word ALL will
suffice if all charts are required.
~BTRANSLATION.LEVELS will ordinarily specify a single level
either 0 or 1 but -1 will cause both to be drawn.
~BOutput device types are:~
~3
~
~MLineprinter                - 0
~NBenson Plotter            - BEN~
~NGenisco                   - GEN
~NHewlett Packard Plotter   - HPP
~NMotorola Display          - MOT
~NDevice on another machine - KER
~0
~
The default value 0 gives lineprinter format.
~
~
~
2) DRAW.CHART(DEVICE.NO,SWITCH)
~BThis procedure performs the main function
of DRAW, translating a tabular representation
of a chart obtained from INPUT.CHART (Section 2)
into output appropriate to the specified DEVICE.NO
where~
~3
~
~N0 - Lineprinter~
~N1 - Graphics device
~0
~
The SWITCH parameter can be set to
allow captions to appear on flow lines.
The settings are as follows:~
~3
~
~T% 8 34
~N~OBIT 0~O
~N0 - Allow captions
~N1 - Suppress captions
~0
~
Output is generated by
DRAW.CHART by
a set of procedures with a device independent specification.
These are as follows:~
~T% 34
~
INIT.CHT -~IThis initialises parameters which control the
centralising of the chart, character size selection and general layout.~
~
DRAW.SHAPE(BOXNO) -~IThis outputs the shape of the specified box
according to its type, and the box number above and offset right of
centre.~
~
DRAW.LINE(X1,Y1,X2,Y2,ARROW) -~IThis outputs a line from X1, Y1 to
X2, Y2 with (non zero) or without an arrow in the middle of it.~
~
DRAW.TEXT(TEXT.VECTOR,X,Y,TEXT.PTR,NO.LINES,EOTX,CHSIZE)~
~IThis outputs NO.LINES lines of text starting from TEXT.PTR within
the TEXT.VECTOR until an EOTX character is encountered. Character size is
determined by CH.SIZE - zero means default to normal.~
~
END.CHT -~IThis allows extra information to be appended to the chart
i.e. date, title, stamping before finishing this chart.~
~
OUTPUT.PAGE -~IThis causes line by line devices (diablo, lineprinter)
to output the complete chart line by line. The plotter does not operate
in this way as pen positioning is unrestricted.~
~BTo produce the required procedure calls, DRAW.CHART firstly
establishes the size of each box on the basis of amount of text it
contains, its
type and the captions surrounding it. Then by examining the ROW
statements for the chart, the vertical coordinates of each box in each
column are calculated. The final phase involves calculating the layout
of the flow links to minimise crossovers and positioning the columns
across the page. This involves several phases in dealing with the more
complex flow patterns.
~BSimple primary flows connecting adjacent boxes in a column are not
considered here because they are drawn directly when the column is
drawn. Flow lines going between columns (intercolumnal flows) and
columnal flows to non adjacent boxes are processed by forming the LINK
TABLE, which has an entry describing each flow link. A flow link is
the basic constituent of a flow path - it is the flow between two
individual boxes in the path. The exact route for each link is
calculated on the basis of minimum number of crossovers with the other
links. Flow paths which have the same destination box as others form a
flow pattern called a complex link, and rather than draw numerous
lines to one box they are broken down to their simplest constituent
flow links. This means that certain links are not drawn to their true
destination but instead to the exit flow link of a box with the same
eventual destination. This break down is achieved by constructing a
BREAK TABLE which has an entry for each constituent flow in the
complex link. This table is processed to alter duplicated flow links
and to minimise the length of the lines to be drawn under the
constraint of minimum conflicting crossovers as the alterations
proceed. A COST TABLE is formed to implement the constraint. Its axes
represent all the potential start and finish points and each element
expresses the number of crossovers occuring with all other links if
this link is drawn.
~BSeveral additional constructs are involved in the detailed design.
For example, a tidying rule is applied which converts an intercolumnal
flow to have no vertical components between the columns. This occurs
most frequently at the top and bottom of columns hence there is a 'top
tidy' and a 'bottom tidy'.
~BIn allocating channels between columns a boundary channel concept
is employed. To explain this in simple terms is awkward but it occurs,
for example, when a channel has to be allocated to a columnal flow
between non adjacent boxes. In this case the boundary channel is the
channel last allocated to a surrounding columnal flow. This does not
just apply to columnal flows but further explanation is left to the
flow charts.
~BA procedure is included which removes any 'null errors'. This is to
avoid 'spikes' occuring in flows which go to a null box and then exit
on the same side.
~BAs DRAW.CHART is quite complex in design the way it
breaks down into procedures is shown below.~
~
Layout of Procedures in DRAW.CHART.~
~
~T% 12 17
DRAW.CHART DOC04.2~
%Adjust box dimensions 4.1~
%Calculate Y coords 4.3~
%%Straighten Row 4.3.1~
%%Create Row vector 4.3.2~
%Create tables 4.4~
%%Fill rest of link entry 4.4.1~
%Fix Vertical links 4.5~
%%Calculate crossover count 4.5.1~
%%Calculate Vertical intersections 4.5.1.1~
%Remove null errors 4.6~
%Break up Complex links 4.7~
%%Create break table 4.7/2~
%%Create cost table 4.7/3~
%Tidy up 4.8~
%%Space for tidy 4.8.1~
%Process columnal links 4.9~
%%Calculate nest count 4.9.1~
%%Allocate channels 4.9.2~
%%Allocate channels cont. 4.9.2/1~
%Outputlinks 4.11~
%Output boxes 4.12~
~
%Subroutines used by DRAW~
%Calculate X exit 4.13~
%Calculate Y exit 4.14~
%Calculate X entry 4.15~
%Calculate Y entry 4.16~
%Calculate length 4.17~
%Output text 4.18~
%Intersection 4.19~
~S1~O3.2 Data Structures
~
~
~T% 17
BOXTAB~IThe BOX TABLE is an imported data structure described
in section 2 (DOC021).~
~
COLTAB~ISee section 2.~
~
BTB~ISee section 2.~
~
TITLE.DIR~Ia list of all the requested chart titles in hash form.
The hash is returned by INPUT.TITLE described in section 2.~
~
TBUFF~IA byte vector containing the current chart title.~
~
LINK~Ia table which describes the more complicated flow
links of a chart. [The simple links joining together
the boxes of a column are processed directly by the
routines which draws a column]. Its fields are as
follows:-~
~
~ISIDE an integer code describing the direction in which
the flow exits from the source box~
~I0 - LEFT; 1 - RIGHT; 2 - VERTICAL~
~ISOURCE an integer giving the source box number.~
~IDEST an integer giving the destination box number.~
~IENTYPE an integer code describing whether the entry
to the destination box is to the top or bottom of the
box i.e. (ENTRY OR EXIT).~
~ICOLS an integer giving the column number of the source box.~
~ICOLD an integer giving the column number of the destination box.~
~IBOTEX a boolean code indicating when true that the flow from the
source box exits from the bottom rather than a side.~
~ITIDY an integer code specifying whether any form of tidying was
carried out on this flow (i.e. TOP,BOTTOM,NONE).~
~ICHAN an integer indicating which channel number has been
allocated to this flow. Initially a large number of channels
(=50) is assumed between each pair of columns and is later
normalised.~
~ITRUEDEST an integer giving the original destination box for
this flow before it was broken down to its constituent parts.~
~IENTSIDE an integer code specifying from which side the flow
reaches the destination box.~
~INCT the nest count is an integer count of the number of entry
and exit points between the entry and exit of a columnal flow
(or intercolumnal flow).~
~IBCHAN an integer specifying the boundary channel which is the
innermost channel already allocated between the entry and exit
points of this flow.~
~IBLINK an integer specifying the link number (i.e. index into the
link table) of the flow associated with BCHAN.~
~IBLDEST an integer specifying the destination box of BLINK.~
~ICOLC an integer specifying the column number relative to which
the channel for this intercolumnal flow is allocated.~
~ICHSIDE a boolean code specifying on which side of COLC the
channel allocated to this intercolumnal lies.~
~IENCLOSURE a bit vector whose bits each represent a link number.
It represents all the links which are enclosed by this link.~
~IOVERLAP a bit vector whose bits represent those links which are
either enclosed by or intersect this link.~
~
ROW~Ia vector of bit significant vectors indexed by box
number whose entries represent individual elements in a row.~
~
ROWSET~Ia compound of all ROW VECTORS representing all boxes
included in a row statement.~
~
BREAK~Ia table generated for each complex link each of whose
entries (except entry 00) represents a constituent flow
in the complex link. It consists of~
~
%Y the Y coordinate of the source~
%LINK index into link table~
%NODE chosen destination box as opposed to TRUE DEST.~
~
COST~Ia table generated for each complex link with all the
potential entry points on one axis and all the
potential exits on the other axis. The contents
express the number of crossovers caused by connecting
the potential entry to the potential exit.~
~
TAG~Ia vector which indicates whether or not the
corresponding break table element has been processed.~
~
ALLOC~Ia table consisting of a set of vectors one for each
column. Each entry represents a vertical position (Y coordinate)
in the column. It is used in positioning boxes.~
~
STOPSET~Ia bit vector indexed by box number. Used during box
positioning for those boxes which cannot be positioned
immediately because all the row information has not
been fully examined at the time.~
~
YFIXED~Ia vector indexed by box number specifying the Y coordinate
value assigned to a box.~
~
ENT.CT~Ia vector with a double entry for each box which holds
a count of the number of flows into each side of the box.~
~
LRCT~Ia vector with two entries, one for each side of a
column which contains a vertical (or columnal) link.
Each entry is a count of the number of crossovers with
other links which would occur if the columnal link was
placed on that side of the column.~
~
DLIST~Ia pair of vectors with an entry for each box. They
record for a column with a columnal link, the box
numbers on each side of the column which are connected
by a flow path to/from the column.~
~
VDLIST~Ia pair of vectors similar to DESTLIST recording boxes
with columnal flow paths in a column with a columnal link
which would cause crossovers.~
~
VERTCT~Ia vector with two entries one for each side of a
column with a columnal flow link. It is similar to
LRCOUNT and is used in conjunction with VDESTLIST to
count the 'noise' or possible crossovers occuring
between the columnal flow under consideration and
other columnal flows in this column.~
~
MINC~Ia vector of pairs of values used for holding the
minimum channel number on either side of a column.~
~
COLWTH~Ia vector of column widths.~
~
COLX~Ia vector of horizontal coordinate values for the
centres of columns.~
~
LGCNO~Ithe link group channel number is a vector indexed by
box number. Each entry holds the channel number allocated to the
flow going to a particular destination box.~
~
MAX.X~Ian integer giving the maximum X coordinates assigned to
the chart by the layout phase of DRAW. This is effectively the
width of the chart in half character units.~
~
MIN.X~Ia literal set to zero which is the initial value assigned to X.~
~
MAX.Y~Ia literal set to 511 which is the initial value assigned to Y
as the top of the page.~
~
MIN.Y~Ian integer giving the final value assigned as a Y
coordinate at the bottom of the diagram.~
~
HWR~Iheight to width ratio is a literal which specifies
the character size in the ratio 2:1. Used for
calculating box size from the amount of text within it.~
~
UNDEF~
NULL~
ANNOT~
STRT~
RECT~
TEST~
FIN~
CIRC~IThese are literals representing box type numerically in
the range 0->7 inclusive.~
~
DATESTR~Ia vector of 10 bytes used for holding the date in a form
suitable for printing.~
~
LINKLIMIT~Ian integer specifying the number of complex links
in a chart.~
~
BOXLIMIT~Ian integer specifying number of boxes in a chart.~
~
ROWLIMIT~Ian integer specifying the number of ROW statements
in the chart specification.~
~
COLIMIT~Ian integer giving the number of columns in a chart.~
~
XMAP, YMAP~ISee Section 5.~
XSCALE, YSCALE~
XD, YD~
XPOS, YPOS~
~
PHGT~
OCT, OCTPTR~
PICPTR, SPCT~ISee Section 7.~
~S1~O4. Compile Jobs
~BThe compile jobs for DRAW are described in section 2.
~Y
~V9 -1
~P
~D15
~HFLOWCHARTS
~
~
~H                DOC041
~V9 -1
~F
@TITLE DOC04(1,9)
@COL 1S-2R-3R-4R-5R-6F
@FLOW 1-2-3-4-5-6
@BOX 1.0
DRAW
@BOX 2.0
@BOX 3.0
@BOX 4.0
PROCEDURES IN MODULE
   DRAW [DOC04.1]
   DRAW CHART [DOC04.2]
@BOX 5.0
#DOC04.1
#DOC04.2
@BOX 6.0
END
@BOX 1.1
#DOC04/1
MODULE(DRAW,DRAW.CHART,HWR,XMAP,YMAP,XSCALE,YSCALE,XD,YD,
COLX,DATESTR,TBUFF,MINX,MINY,MAXX,MAXY,XPOS,YPOS,DATA,
OUTCOM,OCT,OCTPTR,PHGT,PW2,PW3,PWW1,PWW2,PICPTR,SPCT,XM,YM);
$LI HWR=2;
$LI MINX=0,MAXY=512;
*GLOBAL 3;
$IN MAXX,MINY,XD,YD,XSCALE,YSCALE,XMAP,YMAP;
$IN XM,YM,XPOS,YPOS,OCTPTR,PHGT,PICPTR,SPCT;
TYPE BREAKSPEC IS $IN Y,LNK,NODE;
TYPE ECSPEC IS $IN[2] ECSIDE;TYPE MCHOL IS $IN[2]SID;
TYPE DATA IS $IN LENGTH OR $AD[$LO8] CHSTR;
TYPE OUTCOM IS $LO8 OCTYPE $IN HPOS,VPOS DATA PARAMS;
OUTCOM[300] OCT;
$LO8[64] TBUFF;
$LO8[10] DATESTR;
$IN[8] COLWTH,COLX;
$LO8[4096]COST;$LO8[512] ALLOC;
BREAKSPEC[64] BREAK;
$LO64[16]ROW;$LO64 ROWSET;
$LO64 STOPSET; $LO8[64]TAG; ECSPEC[64]ENT.CT; MCHOL[8]MINC;
$IN[2] LRCT,VERTCT; $LO64[2]DLIST,VDLIST;$IN[64] LGCNO;
*GLOBAL 0;
*GLOBAL 5;
$AD PW2,PW3,PW4,PW5,PW6;
$LO64 PWW1,PWW2;
*GLOBAL 0;
@BOX 2.1
@BOX 3.1
@BOX 4.1
LSPEC DRAW($AD[$LO8],$AD[$LO8],$IN,$LO64);
::MU6 PSPEC DRAW.CHART($IN,$IN);
::MC68000 PSPEC DRAW.CHART($IN,$IN);
::PDP LSPEC DRAW.CHART($IN,$IN)
#DOC04.1
#DOC04.2
@BOX 6.1
*END
@END
@TITLE DOC04/1(1,11)
@COL 1S-2R-3F
@FLOW 1-2-3
@BOX 1.0
EXTERNAL ENVIRONMENT
@BOX 2.0
EXTERNAL PROCS
@BOX 3.0
END
@BOX 1.1
::EXTERNALS
@BOX 2.1
$LS CURRENT.INPUT()/$IN;
$LS CURRENT.OUTPUT()/$IN;
$LS DEFINE.IO($IN,$AD[$LO8],$IN32,$IN32)/$IN;
$LS DEFINE.INPUT($IN,$AD[$LO8],$IN32)/$IN;
$LS DEFINE.OUTPUT($IN,$AD[$LO8],$IN32,$IN32)/$IN;
$LS SELECT.INPUT($IN);$LS SELECT.OUTPUT($IN);
$LS END.INPUT($IN,$IN);$LS END.OUTPUT($IN,$IN);
$LS INCH()/$IN;$LS OUTCH($IN);$LS NEXTCH()/$IN;
$LS INBACKSPACE($IN);
$LS SPACES($IN);$LS NEWLINES($IN);
$LS OUTI($IN32,$IN);
$LS BREAKOUTPUT($IN);$LS IPOS()/$IN32;$LS OPOS()/$IN32;
$LS CAPTION($AD[$LO8]);
$LS OUTSTACK(ADDR,ADDR);
$LS TIME.AND.DATE();
$LS I.SIZE()/$IN32;$LS IENQ()/$IN;
$LS O.SIZE()/$IN32;
$LS CREATE.SEGMENT($IN,$AD);$LS MAP($IN,$IN,$IN);
$LS RELEASE.SEGMENT($IN);
$LS INTERCHANGE($IN,$IN);
::MU6 $PS INPUT.CHART($IN,$IN,$IN)/$IN;
::MU6 $PS INPUT.TITLE($AD[$LO8],$IN)/$IN32;
::MC68000 $PS INPUT.CHART($IN,$IN,$IN)/$IN;
::MC68000 $PS INPUT.TITLE($AD[$LO8],$IN)/$IN32;
::PDP $LS INPUT.CHART($IN,$IN,$IN)/$IN;
::PDP $LS INPUT.TITLE($AD[$LO8],$IN)/$IN32;
$PS INIT.CORE($AD[$LO8],$LO64)/$IN;
$PS INITCHT.LPT();$PS INITCHT.COR();
$PS DRAWSHAPE.LPT($IN);$PS DRAWSHAPE.COR($IN);
$PS DRAWLINE.LPT($IN,$IN,$IN,$IN,$IN);
$PS DRAWLINE.COR($IN,$IN,$IN,$IN,$IN);
$PS DRAWTEXT.LPT($AD[$LO8],$IN,$IN,$IN,$IN,$LO8,$IN);
$PS DRAWTEXT.COR($AD[$LO8],$IN,$IN,$IN,$IN,$LO8,$IN);
$PS OUTPUTPAGE.LPT();$PS OUTPUTPAGE.COR();
$PS ENDCHT.LPT();$PS ENDCHT.COR();
$PS END.LPT();$PS END.CORE();
TYPE BOXSPECS IS $IN COL.LINK,ROW.LINK,PFLOW.LINK,YCOORD
$IN SFLOWLINK,TEXT.PTR,PFLOW.TEXT,SFLOW.TEXT,HT,TEXTPTR1
$LO8 T,BOXHT,BOXWTH,COL,INFLOW,LAB.COUNT,PLANTED,YFIXED,BOXHT1,BOXWTH1;
BOXSPECS[64] BOXTAB;$IN[8]COLTAB;
$LO8[8192] BTB;
$IN ROWLIMIT,BOXLIMIT,COLIMIT;
$AD PW0,PW1;
$IM$LI EOBWC;
$IM$LI$IN32 SYS14.SEGSIZE;
::MU6 $IM$LI WORKSEG;
@BOX 3.1
::END
@END
@TITLE DOC04.1(1,9)
@COL 1S-2R-11T-4R-5T-12T-13R-16R-14F
@COL 7R-6T-8R-17R-9T-10R-18R-15C
@ROW 11-7
@FLOW 1-2-11OK-4-5Y-7-6N-8-17-9Y-10-18-12Y-13-16-14
@FLOW 6Y-12N-4
@FLOW 5N-12
@FLOW 15-13
@FLOW 9N-12
@FLOW 11FAULT-16
@BOX 1.0
DRAW(FILINP,FILOUT,LEVEL,DEVICE)
@BOX 2.0
INPUT CHART TITLES
SELECT FILINP AS INPUT
@BOX 11.0
INITIALISE DEVICE AND
CREATE OUTPUT STREAM
@BOX 4.0
INPUT TITLE [DOC02.1]
@BOX 5.0
CHART NEEDED?
@BOX.6
CHART FAULTY?
@BOX 7.0
INPUT CHART [DOC02.2]
@BOX 8.0
OUTPUT TITLE ON CURRENT STREAM
DRAW CHART [DOC04.2]
@BOX 17.0
OUTPUT BUFFERED CHART
IF LPT
@BOX 9.0
SECOND LEVEL SPECIFIED?
@BOX 10.0
REPLACE FIRST LEVEL BOXTAB
ENTRIES BY SECOND
DRAW CHART [DOC04.2]
@BOX 18.0
OUTPUT BUFFERED CHART
IF LPT
@BOX 12.0
ALL CHARTS DONE?
@BOX 13.0
END DRAWING
@BOX 16.0
BREAKOUTPUT AND RESTORE
ORIGINAL I/O
@BOX 14.0
END
@BOX 15.0
END OF
FILE
@BOX 1.1
PROC DRAW(FILE,FILOUT,LEVEL,DEVICE);
PSPEC OUTITLE();
PROC OUTITLE;
$IN I;
-1=>I;
$WH TBUFF[1+>I]/='$L DO OUTCH(TBUFF[I]) OD
NEWLINES(1);
END
$IN32[16] TITLE.DIR;
$IN TDINDEX,CHCT,OLD.IN,OLD.OUT,IN,OUT,ERR;
$IN TITNO,DEVNO,DSEG1,DSEG2,BOXNO;
$IN32 THASH;
$LO8[2] NULLHDR;
0 => NULLHDR[0] => NULLHDR[1];
::PDP CREATE.SEGMENT(-1,%2000);MAP(PW1=>DSEG1,5,1);
::PDP CREATE.SEGMENT(-1,%2000);MAP(PW1=>DSEG2,6,1);
::MU6 CREATE.SEGMENT(-1,%10000);INTERCHANGE(PW1=>DSEG1,WORKSEG);
::MC68000 RELEASESEGMENT(48);CREATESEGMENT(48,%4000);
::MC68000 RELEASESEGMENT(49);CREATESEGMENT(49,%4000);
::MC68000 RELEASESEGMENT(50);CREATESEGMENT(50,%4000);
::MC68000 RELEASESEGMENT(51);CREATESEGMENT(51,%4000);
::MC68000 MAP(48,-1,0);MAP(49,-1,0);MAP(50,-1,0);MAP(51,-1,0);
@BOX 2.1
0 => TDINDEX => CHCT;
WHILE NEXTCH() /= '@ AND TDINDEX < 15 DO
INPUT.TITLE(^TBUFF,0) => TITLE.DIR[1+>TDINDEX];OD INCH();
CURRENT.INPUT() => OLD.IN; CURRENT.OUTPUT() => OLD.OUT;
SELECT.INPUT(DEFINE.INPUT(-1,FILE,%10) => IN);
@BOX 11.1
IF DEVICE = 0 THEN
   0 => DEVNO;
   DEFINEOUTPUT(-1,FILOUT,0,0) => OUT;
ELSE
   1 => DEVNO;
   INIT.CORE(FILOUT,DEVICE)=>OUT;
FI
IF OUT < 0
@BOX 4.1
SELECT.OUTPUT(OLD.OUT);
IF INPUT.TITLE(^TBUFF,1) => THASH= 0, -> END.OF.FILE;
@BOX 5.1
0 => TITNO;
WHILE 1+>TITNO=<TDINDEX AND TITLE.DIR[TITNO]/=
THASH DO OD
IF TITLE.DIR[1] = "ALL" OR TITNO =< TDINDEX
@BOX 7.1
IF LEVEL < 0 THEN
   INPUT.CHART(0,0-LEVEL,0)=>ERR;
ELSE
   INPUT.CHART(LEVEL,-1,0)=>ERR;
FI
1+>BOXLIMIT;
@BOX 6.1
1+>CH.CT;
IF ERR < 0
@BOX 8.1
OUTITLE();SELECT.OUTPUT(OUT);
DRAW.CHART(DEVNO,LEVEL+1&2->>1);
@BOX 17.1
IF DEVICE = 0 THEN
   OUTPUT.PAGE.LPT();
FI
@BOX 9.1
IF LEVEL >= 0
@BOX 10.1
FOR BOXNO < BOXLIMIT DO
   TEXTPTR1 OF BOXTAB[BOXNO] =>
      TEXTPTR OF BOXTAB[BOXNO];
   BOXHT1 OF BOXTAB[BOXNO] =>
      BOXHT OF BOXTAB[BOXNO];
   BOXWTH1 OF BOXTAB[BOXNO] =>
      BOXWTH OF BOXTAB[BOXNO];
OD
DRAW.CHART(DEVNO,0-LEVEL);
@BOX 18.1
IF DEVICE=0 THEN
   OUTPUT.PAGE.LPT();
FI
@BOX 12.1
SELECTOUTPUT(OUT);
IF OSIZE() - OPOS() < %4000 THEN
   BREAKOUTPUT(OUT);
   OUTHDR(^NULLHDR);
FI
IF CHCT /= TDINDEX OR
TITLE.DIR[1] = "ALL"
@BOX 13.1
SELECTOUTPUT(OUT);
IF DEVICE = 0 THEN
   END.LPT();
ELSE
   END.CORE();
FI
ENDOUTPUT(OUT,0);
@BOX 16.1
SELECT.INPUT(OLD.IN);SELECT.OUTPUT(OLD.OUT);
END.INPUT(IN,0);
::PDP RELEASE.SEGMENT(DSEG1); RELEASE.SEGMENT(DSEG2);
::MU6 INTERCHANGE(WORKSEG,DSEG1);RELEASE.SEGMENT(DSEG1);
::MC68000 RELEASE.SEGMENT(48);RELEASE.SEGMENT(49);
::MC68000 RELEASE.SEGMENT(50);RELEASE.SEGMENT(51);
NEWLINES(1);EXIT;
@BOX 14.1
END
@BOX 15.1
ENDOFFILE:;
@END
@TITLE DOC04.2(1,9)
@COL 1S-2R-3R-4R-5R-6R-7R-8F
@FLOW 1-2-3-4-5-6-7-8
@BOX 1.0
DRAW CHART(DEVICE NO,SWITCH)
@BOX 2.0
READ DATE
INITIALISE TABLES
@BOX 3.0
CALCULATE DIMENSIONS OF CHART
AND LAY OUT BOXES IN COLUMNS
@BOX 4.0
INITIALISE CHART FOR SPECIFIED DEVICE
@BOX 5.0
CALCULATE ROUTING AND
DRAW FLOW LINKS
@BOX 6.0
DRAW BOXES
@BOX 7.0
END CHART
@BOX 8.0
END
@BOX 1.1
PROC DRAW.CHART(DEVNO,DR.SW);
#DOC04.2/1
::TEMPORARY
$IN[64] ROWLINKS;
$IN BLT,CLT,RLT;
BOXLIMIT=>BLT;ROWLIMIT=>RLT;
COLIMIT=>CLT;
FOR I < BOXLIMIT DO
   ROWLINK OF BOXTAB[I]=>ROWLINKS[I];
OD
::END OF TEMP
0 => LINKLIMIT;
@BOX 2.1
TIME.AND.DATE();
PWW1=>DATE->>7/675=>DATE;
59->DATE*4-1=>DATE;
DATE/1461=>YEAR;
YEAR*1461-:DATE+4/4=>DAY;
DAY*5-3=>TEMP/153=>MONTH;
MONTH*153-:TEMP+5/5=>DAY;
IF 3+>MONTH > 12 THEN
   12->MONTH;1+>YEAR;
FI
DAY/10+'0=>DATESTR[0];
DAY/10*10-:DAY+'0=>DATESTR[1];'/=>DATESTR[2];
MONTH/10+'0=>DATESTR[3];
MONTH/10*10-:MONTH+'0=>DATESTR[4];'/ => DATESTR[5];
YEAR/10+'0=>DATESTR[6];
YEAR/10*10-:YEAR+'0=>DATESTR[7];'] => DATESTR[8];
FOR COLNO < 8 DO
   0 => COLWTH[COLNO];
OD
@BOX 3.1
#DOC04.2.1
#DOC04.3
#DOC04.4
@BOX 4.1
IF DEVNO = 0 THEN
   INIT.CHT.LPT();
ELSE
   INIT.CHT.COR();
FI
@BOX 5.1
IF LINKLIMIT > 1 THEN
#DOC04.5
#DOC04.6
#DOC04.7
#DOC04.8
#DOC04.9
#DOC04.11
FI
@BOX 6.1
#DOC04.12
@BOX 7.1
IF DEVNO = 0 THEN
   END.CHT.LPT();
ELSE
   END.CHT.COR();
FI
::TEMP
BLT=>BOXLIMIT;RLT=>ROWLIMIT;
CLT=>COLIMIT;
FOR I < BOXLIMIT DO
   ROWLINKS[I]=>ROWLINK OF BOXTAB[I];
OD
::END OF TEMP
@BOX 8.1
END
@END
@TITLE DOC04.2/1(1,9)
@COL 1S-2R-3R-4F
@BOX 1.0
@BOX 2.0
@BOX 3.0
@BOX 4.0
@BOX 1.1
::DECLARATIONS FOR DRAW CHART
@BOX 2.1
TYPE LINKSPEC IS $IN SOURCE,DEST,COLS,COLD,CHAN,TRUEDEST,NCT,BCHAN,BLINK,BLDEST
$IN COLC,SIDE,ENTSIDE $LO8 TIDY,CHSIDE,ENTYPE,BOTEX $LO64 ENCLOSURE,OVERLAP;
LINKSPEC[32] LINK;
$IN I,J,K,YEAR,MONTH,DAY,TEMP,LINKLIMIT,BOXNO,COLNO,STALK,EXLINK;
$IN32 SECS,DATE;
$LI UNDEF=0,NULL=1,ANNOT=2,STRT=3,RECT=4,TEST=5,FIN=6,CIRC=7;
$LI XGAP=12,YGAP=6,MAXCHAN=50,LARGE.NO = 20000,COSTSIZE = 64;
$LI EX=0, ENTRY=1, TITLE=0, TEXT=1, LINE=2, SHAPE=3;
$LI LEFT=0,RIGHT=1,VERT=2,NONE=0,TOP=1,BOTTOM=2,ARROW=1,NOARROW=0;
$LI ENDC = 254, ENDBATCH = 255, NOFTYPES = 8;
@BOX 3.1
PSPEC XEXIT($IN)/$IN;PSPEC YEXIT=XEXIT;
PSPEC XENTRY=XEXIT; PSPEC YENTRY=YEXIT; PSPEC LENGTH($IN)/$IN;
PSPEC INTERSECT($IN,$IN)/$IN; PSPEC IABS($IN)/$IN;
PROC IABS(I);IF I < 0 THEN 0-I => IABS;ELSE I => IABS;FI END
#DOC04.13
#DOC04.14
#DOC04.15
#DOC04.16
#DOC04.17
#DOC04.19
@BOX 4.1
::END
@END
@TITLE DOC04.2.1(1,9)
@COL 1S-2T-5R-6T-7R-8T-10R-11T-12R-13F
@FLOW 1-2-5-6-7-8-10-11-12-13
@BOX 1.0
BOX DIMENSIONS
COL DIMENSIONS
@BOX 2.0
FOR EVERY BOX
@BOX 5.0
ADJUST BOX DIMENSIONS
DEPENDING ON TYPE
CALCULATE LENGTH
OF PRIMARY AND SECONDARY
CAPTIONS.
ADJUST COLUMN WIDTH
@BOX 6.0
END FOR
@BOX 7.0
INITIALISE LHS OF CHART
@BOX 10.0
CALCULATE XCOORD OF COLUMN
@BOX 8.0
FOR EVERY COLUMN DO
@BOX 11.0
END FOR
@BOX 12.0
SET MAX X
@BOX13.0
END
@BOX 1.1
BOX.DIMENSIONS:BEGIN;
$IN J,K,WIDTH,HEIGHT,PREVX,I;
PSPEC MAX($IN,$IN)/$IN;
PROC MAX(I,J);
I => MAX;
IF I < J THEN
   J => MAX;
FI
END
@BOX 2.1
FOR BOXNO < BOXLIMIT DO
@BOX 5.1
IF T OF BOXTAB[BOXNO] => I =< NULL THEN
   0 => WIDTH => HEIGHT;
ELSE
   BOXHT OF BOXTAB[BOXNO] => HEIGHT;BOXWTH OF BOXTAB[BOXNO] => WIDTH;
   IF I = CIRC THEN
      WIDTH +(HEIGHT*HWR/4) => WIDTH;
   ELSE
      IF I = TEST OR I = RECT THEN
         IF WIDTH < 6 THEN
            6 => WIDTH;
         FI
      FI
      IF I = TEST THEN
         HEIGHT*HWR+WIDTH=>WIDTH;
      FI
   FI
FI
HEIGHT => HT OF BOXTAB[BOXNO];WIDTH => BOXWTH OF BOXTAB[BOXNO];
IF DR.SW & 1 = 0 THEN
LENGTH(PFLOW.TEXT OF BOXTAB[BOXNO]) <<- 1 => J;
LENGTH(SFLOW.TEXT OF BOXTAB[BOXNO]) <<- 1 => K;
ELSE 0 => J => K FI
MAX(MAX(WIDTH+K,J),COLWTH[COL OF BOXTAB[BOXNO]])/2*2+1 => COLWTH[COL OF BOXTAB[B
OXNO]];
@BOX 6.1
OD
@BOX 7.1
0 => PREVX;
@BOX 8.1
FOR COLNO < COLIMIT DO
@BOX 10.1
IF DEVNO > 2 THEN
   2 +> COLWTH[COLNO];
FI
PREVX + XGAP + COLWTH[COLNO] => COLX[COLNO] + COLWTH[COLNO] => PREVX;
@BOX 11.1
OD
@BOX 12.1
PREVX + XGAP => MAXX
@BOX 13.1
END
@END
@TITLE DOC04.3(1,9)
@COL 1S-2R-3R-4R-18T-5R-7T-8R-9R-10T-25R-16R-17T-19T
@COL 11R-12R-26T-27R-13T-14R-15R-20T-21R-22T-23F
@ROW 3-11
@ROW 25-20
@FLOW 1-2-3-4-18-5-7N-8-9-10N-11-12-26N-27-13Y-14-15-16-17N-19-20Y-21-22N-23
@FLOW 10Y-25-16
@FLOW 13N-15
@FLOW 7Y-9
@FLOW 17Y-7
@FLOW 22Y-4
@FLOW 20N-22
@FLOW 26Y-15
@BOX 1.0
CALCULATE YCOORDS
@BOX 2.0
COLLECT ROW INFORMATION INROW VECTOR AND ROWSET[DOC04.3.2]
@BOX 3.0
INITIALISE ALLOC[]
CLEAR FIXED FLAGS AND INIT MINY
SET ENTRY/EXIT STALK LENGTH
ACCORDING TO DEVICE TYPE
@BOX 4.0
INIT STOPSET
@BOX 5.0
INIT LY,FLAG,BOX
@BOX 7.0
BOX ALREADY FIXED?
@BOX 8.0
SET BOX YCOORD
@BOX 9.0
FORM GAP AND CALC MINY
@BOX 10.0
BOX IN UNPROCESSED ROW?
@BOX 11.0
FIX YCOORD
@BOX 12.0
CALCULATE TOP AND BOTTOM YCOORDS
@BOX 13.0
PRIMARY EXIT?
@BOX 14.0
ADJUST BOTTOM COORD
@BOX 15.0
MARK POSITION IN ALLOC
@BOX 16.0
ADVANCE TO BOX BELOW
@BOX 17.0
BOX BELOW AND FLAG NOT SET?
@BOX 18.0
FOR EACH COLUMN
@BOX 19.0
END FOR
@BOX 20.0
ANY BOXES IN STOPSET?
@BOX 21.0
STRAIGHTEN ROW [DOC04.3.1]
@BOX 22.0
ANY BOXES IN STOPSET
@BOX 23.0
END
@BOX 25.0
PUT BOX IN STOPSET AND SET FLAG
@BOX 26.0
NULL BOX?
@BOX 27.0
ALLOW FOR ENTRYPOINT
@BOX 1.1
CALCULATE.YCOORDS:BEGIN;
$IN I,J,LY,START,FINISH,FLAG,ROWCT;
@BOX 2.1
#DOC04.3.2
@BOX 3.1
MAXY => MINY;
FOR J < 512 DO
   0 => ALLOC[J];
OD
FOR BOXNO < BOXLIMIT DO
   0 => YFIXED OF BOXTAB[BOXNO];
OD
IF DEVNO < 2 THEN
   2 => EXLINK;1  => STALK;
ELSE
   3 => EXLINK => STALK;
FI
@BOX 4.1
0 => STOPSET;
@BOX 18.1
FOR COLNO < COLIMIT DO
@BOX 5.1
MAXY-6 => LY;0 => FLAG;
COLTAB[COLNO] => BOXNO;
@BOX 7.1
IF YFIXED OF BOXTAB[BOXNO] /= 0
@BOX 8.1
LY-HT OF BOXTAB[BOXNO] => YCOORD OF BOXTAB[BOXNO];
@BOX 9.1
YCOORD OF BOXTAB[BOXNO]-HT OF BOXTAB[BOXNO]-YGAP+1/2*2 => LY;
IF PFLOW.LINK OF BOXTAB[BOXNO] /= COL.LINK
   OF BOXTAB[BOXNO] THEN
2 -> LY;
FI
IF LY < MINY THEN
   LY => MINY;
FI
@BOX 10.1
IF 1 <<- BOXNO & ROWSET = 0
@BOX 11.1
1 => YFIXED OF BOXTAB[BOXNO];
@BOX 12.1
YCOORD OF BOXTAB[BOXNO] + HT OF BOXTAB[BOXNO]
   => FINISH - (HT OF BOXTAB[BOXNO]<<-1) => START;
@BOX 13.1
IF PFLOW.LINK OF BOXTAB[BOXNO] = 0
@BOX 14.1
EXLINK -> START;
@BOX 15.1
START - 1 => I;
WHILE 1 +> I =<FINISH DO
     1 <<- COLNO !> ALLOC[I];
OD
@BOX 16.1
COL.LINK OF BOXTAB[BOXNO] => BOXNO;
@BOX 17.1
IF BOXNO /= 0 AND FLAG = 0
@BOX 19.1
OD
@BOX 20.1
IF STOPSET = 0
@BOX 21.1
#DOC04.3.1
@BOX 22.1
IF STOPSET /= 0
@BOX 23.1
END
@BOX 25.1
1 => FLAG;
1 <<- BOXNO !> STOPSET;
@BOX 26.1
IF T OF BOXTAB[BOXNO] =< NULL
@BOX 27.1
EXLINK +> FINISH;
@END
@TITLE DOC04.3.1(1,9)
@COL 1S-2R-3T-4T-5R-6T-7T-8R-9T-10T-11T-12R-13T-14R-15T
@COL 16T-17R-18T-19T-20R-21T-22F
@ROW 4-16
@FLOW 1-2-3-4Y-5-6-7Y-8-9-10-11Y-12-13-14-15-16Y-17-18-19Y-20-21-22
@FLOW 4N-15
@FLOW 7N-9
@FLOW 11N-13
@FLOW 16N-22
@FLOW 19N-21
@BOX 1.0
STRAIGHTEN ROW
@BOX 2.0
SET ROW ERROR
@BOX 3.0
FOR EACH ROW
@BOX 4.0
ROW EMPTY OR ANY ROW
ELEMENT NOT IN STOPSET?
@BOX 5.0
INIT YCOORD OF ROW
@BOX 6.0
FOR EVERY BOX
@BOX 7.0
BOX IN THIS ROW?
@BOX 8.0
SET YCOORD OF ROW
TO MIN SO FAR
@BOX 9.0
END FOR
@BOX 10.0
FOR EVERY BOX
@BOX 11.0
BOX IN THIS ROW?
@BOX 12.0
SET YCOORD.MARK AS FIXED
@BOX 13.0
END FOR
@BOX 14.0
REMOVE ROW FROM ROWSET
THIS ROW NOW EMPTY
CLEAR ROW ERROR
@BOX 15.0
END FOR
@BOX 16.0
ROW ERROR?
@BOX 17.0
MESSAGE - ROW ERROR
@BOX 18.0
FOR EACH ROW
@BOX 19.0
DOES THIS ROW
CONTRIBUTE TO STOPSET?
@BOX 20.0
REMOVE ROW FROM ROWSET
THIS ROW NOW EMPTY
@BOX 21.0
END FOR
@BOX 22.0
END
@BOX 1.1
STRAIGHTEN.ROWS:BEGIN
$IN I,J,LY,ROWERROR,COUT;
@BOX 2.1
1 => ROWERROR;
@BOX 3.1
FOR I < ROWCT DO
@BOX 4.1
IF ROW[I] = 0 OR STOPSET -= %F(16) & ROW [I] /= 0
@BOX 5.1
MAXY => LY;
@BOX 6.1
FOR BOXNO < BOXLIMIT DO
@BOX 7.1
IF 1 <<- BOXNO & ROW[I] = 0
@BOX 8.1
IF LY > YCOORD OF BOXTAB[BOXNO] THEN
   YCOORD OF BOXTAB[BOXNO] => LY;
FI
@BOX 9.1
OD
@BOX 10.1
FOR BOXNO < BOXLIMIT DO
@BOX 11.1
IF 1 <<- BOXNO & ROW[I] = 0
@BOX 12.1
1 => YFIXED OF BOXTAB[BOXNO];
IF LY-=HT OF BOXTAB[BOXNO] & 1 /= 0 THEN
   1 +> LY;
FI
LY => YCOORD OF BOXTAB[BOXNO];
@BOX 13.1
OD
@BOX 14.1
0 => ROWERROR;
ROW[I] -= %F(16) &> ROWSET;
0 => ROW[I];
@BOX 15.1
OD
@BOX 16.1
IF ROWERROR = 0
@BOX 17.1
CURRENTOUTPUT()=>COUT;
SELECTOUTPUT(0);
CAPTION(%"$LROW ERROR");
SELECTOUTPUT(COUT);
@BOX 18.1
FOR I < ROWCT DO
@BOX 19.1
IF ROW[I]&STOPSET = 0
@BOX 20.1
ROW[I] -= %F(16) &> ROWSET;
@BOX 21.1
OD
@BOX 22.1
END
@END

@TITLE DOC04.3.2(1,7)
@COL 1S-2T-3R-4T-5T-6R-7T-8T-9R-10T-11R-12T-17T-13R-15T-16F
@FLOW 1-2Y-3-4-5N-6-7-8N-9-10Y-11-12-17N-13-15-16
@FLOW 2N-16
@FLOW 5Y-15
@FLOW  8Y-12
@FLOW 10N-12
@FLOW 17Y-7
@BOX 1.0
CREATE ROW VECTOR
INITIALISE ROWSET
@BOX 2.0
ANY ROW STATEMENTS?
@BOX 3.0
INIT NOFROWS
@BOX 4.0
FOR EACH BOX
@BOX 5.0
IS ROW LINK ZERO?
@BOX 6.0
CREATE ROW VECTOR CONSISTING OF
CURRENT BOX AND ROW LINK
@BOX 7.0
FOR EACH REMAINING BOX
@BOX 8.0
IS ROW LINK ZERO
@BOX 9.0
CREATE ROW VECTOR CONSISTING OF
THIS BOX AND ITS ROW LINK
@BOX 10.0
DO THESE TWO ROW VECTORS INTERSECT?
@BOX 11.0
MERGE ROW VECTORS
CLEAR ROW LINK FOR THIS BOX
@BOX 12.0
END FOR
@BOX 13.0
INCR ROW COUNT
SAVE COMPOUND ROW VECTOR
UPDATE ROWSET
@BOX 15.0
END FOR
@BOX 16.0
END
@BOX 17.0
ANY MERGES?
@BOX 1.1
CREATE.ROW.VECTOR:BEGIN
$LO8 MERGE;
$IN I,J,T;
$LO64 RSET,TSET,USET;
0 => ROWSET=>ROWCT;
@BOX 2.1
IF ROWLIMIT = 0
@BOX 3.1
-1 => ROWCT;
@BOX 4.1
FOR BOXNO < BOXLIMIT DO
@BOX 5.1
IF ROW.LINK OF BOXTAB[BOXNO] = 0
@BOX 6.1
1 <<- BOXNO!(1<<-ROW.LINK OF BOXTAB[BOXNO]=>USET) => RSET;
@BOX 7.1
BOXNO => J; 0 => MERGE;
WHILE 1+>J < BOXLIMIT DO
@BOX 8.1
IF ROW.LINK OF BOXTAB[J] => T = 0
@BOX 9.1
1 <<- J!(1<<-T=>USET) => TSET;
@BOX 10.1
IF RSET & TSET = 0
@BOX 11.1
TSET !> RSET;
1 => MERGE; 0 => ROW.LINK OF BOXTAB[J];
@BOX 12.1
OD
@BOX 17.1
IF MERGE /= 0
@BOX 13.1
RSET => ROW[1+>ROWCT] !> ROWSET;
1 +> ROWLIMIT;
@BOX 15.1
OD
@BOX 16.1
1+> ROWCT
END
@END
@TITLE DOC04.4(1,7)
@COL 1S-2R-3R-4T-6T-7T-8R-9T-10R-11T-12F
@FLOW 1-2-3-4-6Y-7N-8-9Y-10-11-12
@FLOW 6N-11
@FLOW 7Y-9N-11
@BOX 1.0
CREATE TABLES
@BOX 2.0
CLEAR ALL ENTRY COUNTS TO ZERO
@BOX 3.0
INIT LINK INDEX
@BOX 4.0
FOR EACH BOX
@BOX 6.0
ANY PRIMARY FLOW?
@BOX 7.0
PRIMARY TO BOX BELOW?
@BOX 8.0
FORM LINK ENTRY FOR THIS
BOX SPECIFYING FLOW
FROM BOTTOM
@BOX 9.0
ANY SECONDARY FLOW?
@BOX 10.0
FORM LINK ENTRY FOR THIS
BOX SPECIFYING FLOW
FROM SIDE
@BOX 11.0
END FOR
@BOX 12.0
BODY OF FILLREST
[DOC04.4.1]
END
@BOX 1.1
CREATE.TABLES:BEGIN
PSPEC FILLREST($IN,$IN);
#DOC04.4.1
@BOX 2.1
FOR BOXNO < BOXLIMIT DO
   0 => ECSIDE[0] OF ENT.CT[BOXNO]
   => ECSIDE[1] OF ENT.CT[BOXNO];
OD
@BOX 3.1
1 => LINKLIMIT;
@BOX 4.1
FOR BOXNO < BOXLIMIT DO
@BOX 6.1
IF PFLOW.LINK OF BOXTAB[BOXNO] = 0
@BOX 7.1
IF PFLOW.LINK OF BOXTAB[BOXNO] = COL.LINK OF BOXTAB[BOXNO]
@BOX 8.1
FILLREST(PFLOW.LINK OF BOXTAB[BOXNO],1);
@BOX 9.1
IF SFLOW.LINK OF BOXTAB[BOXNO] = 0
@BOX 10.1
FILLREST(SFLOW.LINK OF BOXTAB[BOXNO],0);
@BOX 11.1
OD
@BOX 12.1
END
@END
@TITLE DOC04.4.1(1,7)
@COL 1S-2R-3T-4R-5R-6F
@COL 7R
@ROW 4-7
@FLOW 1-2-3N-4-5-6
@FLOW 3Y-7-5
@BOX 1.0
PROC FILLRESTOFLINKENTRY(BOXNO,BOOLEAN)
@BOX 2.0
SELECT LINK ENTRY
SET SOURCE,BOTEX
    DEST
    TRUEDEST
    TIDY STATUS
    ENTRY TYPE
    SOURCE & DEST COLUMN NOS
CLEAR CHANNEL
      ENCLOSURE,OVERLAP
      NEST COUNT
      BOUNDARY LINK
      BOUNDARY DEST
INIT  BOUNDARY CHANNEL
@BOX 3.0
COLUMNAL LINK?
@BOX 4.0
SET SIDE AND ENTRYSIDE TO
INDICATE LEFT OR RIGHT SIDE
FLOW EXIT AND OPPOSITE SIDE
FLOW ENTRANCE TO DESTINATION
ACCORDING TO COLUMN NOS
INCREMENT ENTRY COUNT
OF DEST BOX
@BOX 5.0
INCREMENT LINK NO
@BOX 6.0
RETURN
END
@BOX 7.0
SET SIDE AND ENTRYSIDE TO
INDICATE VERTICAL FLOW OUT OF
THIS BOX AND VERTICAL ENTRY
TO THE DESTINATION
@BOX 1.1
PROC FILLREST(BOX,EXITPOINT);
$IN J;
@BOX 2.1
LINK.LIMIT => I;
EXITPOINT => BOTEX OF LINK[I]; NONE => TIDY OF LINK[I]; BOX => DEST OF LINK[I] =
> TRUEDEST OF LINK[I];
ENTRY => ENTYPE OF LINK[I]; 0 => CHAN OF LINK[I] => NCT OF LINK[I] => BLDEST OF
LINK[I] => BLINK OF LINK[I];
MAXCHAN => BCHAN OF LINK[I]; BOXNO => SOURCE OF LINK[I];
COL OF BOXTAB[BOXNO] => COLC OF LINK[I] => COLS OF LINK[I]; COL OF BOXTAB[BOX] =
> COLD OF LINK[I];
0 => ENCLOSURE OF LINK[I] => OVERLAP OF LINK[I];
@BOX 3.1
IF COLS OF LINK[I] = COLD OF LINK[I]
@BOX 4.1
IF COLS OF LINK[I] < COLD OF LINK[I] THEN
   1 => SIDE OF LINK[I] => CHSIDE OF LINK[I];
ELSE
   0 => SIDE OF LINK[I] => CHSIDE OF LINK[I];
FI
1-SIDE OF LINK[I] => ENTSIDE OF LINK[I]=>J;
1 +> ECSIDE[J] OF ENT.CT[BOX];
@BOX 5.1
1 +> LINKLIMIT;
@BOX 6.1
END
@BOX 7.1
VERT => SIDE OF LINK[I] => ENTSIDE OF LINK[I] => CHSIDE OF LINK[I];
@END
@TITLE DOC04.5(1,6)
@COL 1S-2R-3T-4R-5R-20T-21R-22T-23F
@COL 6T-25T-7T-8R-11T-26T-12T-13R-18T-14T-15R-16T-17R-19T-24R
@ROW 2-6
@ROW 20-17
@FLOW 1-2-3N-4-5-6-25Y-7N-8-11-26N-12Y-13-18-14N-15-16Y-17-19-20N-21-22Y-23
@FLOW 7Y-19
@FLOW 12N-18
@FLOW 16N-19
@FLOW 20Y-24-22N-3Y-5
@FLOW 14Y-19
@FLOW 25N-19
@FLOW 26Y-18
@BOX 1.0
FIX VERTICAL LINKS
@BOX 2.0
CLEAR FLAG
@BOX 3.0
FLAG SET?
@BOX 4.0
EMPTY SUSPENDED SET
@BOX 5.0
ALLFIXED,NONEFIXED
INIT XOVER BALANCE
@BOX 6.0
FOR EVERY LINK
@BOX 7.0
LINK SUSPENDED?
@BOX 8.0
CALCULATE XOVER COUNT
[DOC04.5.1]
CLEAR FIXED
@BOX 11.0
FOR EACH SIDE
@BOX 12.0
LINK MAY BE FIXED ON THIS SIDE?
@BOX 13.0
SET SIDE, ENTRYSIDE; INCREMENT ENTRYCOUNT
SET FIXED; CLEAR NONE FIXED
@BOX 14.0
FIXED?
@BOX 15.0
CLEAR ALLFIXED; CALC XOVER BALANCE
@BOX 16.0
LOWEST BALANCE SO FAR?
@BOX 17.0
MAKE LINK A SUSPENSION CANDIDATE
@BOX 18.0
END FOR
@BOX 19.0
END FOR
@BOX 20.0
NOT ALLFIXED AND NONEFIXED?
@BOX 21.0
CLEAR FLAG
@BOX 22.0
ALLFIXED AND NONE SUSPENDED
@BOX 23.0
END
@BOX 24.0
SUSPEND CANDIDATE
SET FLAG
@BOX 25.0
VERTICAL LINK?
@BOX 26.0
FIXED ALREADY?
@BOX 1.1
FIX.VERTICAL.LINKS: BEGIN;
$IN FLAG,NONEFIXED,ALLFIXED,MINLR,FIXED,DIFF,SUSPCAND,S;
$LO64 SUSP;


@BOX 2.1
0 => FLAG;
@BOX 3.1
IF FLAG /= 0
@BOX 4.1
0 => SUSP;
@BOX 5.1
1 => NONEFIXED => ALLFIXED;
LARGE.NO => MINLR;
@BOX 6.1
0 => I;
WHILE 1+>I < LINK.LIMIT DO
@BOX 25.1
IF SIDE OF LINK[I] /= VERT
@BOX 7.1
IF 1 <<- I & SUSP /= 0
@BOX 8.1
#DOC04.5.1
0 => FIXED;
@BOX 11.1
FOR S < 2 DO
@BOX 26.1
IF FIXED /= 0
@BOX 12.1
IF LRCT[1-S] - LRCT[S] - VERTCT[S] < 0
@BOX 13.1
S => SIDE OF LINK[I] => ENTSIDE OF LINK[I];
1 +> ECSIDE[S] OF ENT.CT[DEST OF LINK[I]];
0 => NONEFIXED; 1 => FIXED;
@BOX 18.1
OD
@BOX 14.1
IF FIXED /= 0
@BOX 15.1
0 => ALLFIXED;
IF LRCT[LEFT] - LRCT[RIGHT] => DIFF < 0 THEN
   0 -:> DIFF;
FI
@BOX 16.1
IF DIFF >= MINLR
@BOX 17.1
DIFF => MINLR; I => SUSPCAND;
@BOX 19.1
OD
@BOX 20.1
IF ALLFIXED = 0 AND NONEFIXED = 1
@BOX 21.1
0 => FLAG;
@BOX 22.1
IF SUSP /= 0 OR ALLFIXED = 0
@BOX 23.1
END
@BOX 24.1
1 => FLAG;
1 <<- SUSPCAND !> SUSP;
@END
@TITLE DOC04.5.1(1,9)
@COL 14R
@COL 1S-16R-2T-3T-5T-7R-8T-18R-6T-9T-10R-17T-11R-12T-13F
@COL 15R
@ROW 9-15
@ROW 14-10
@FLOW 1-16-2-3N-5Y-7-8Y-18-6N-9N-10-17N-11-12-13
@FLOW 3Y-12
@FLOW 5N-12
@FLOW 6Y-15-12
@FLOW 8N-12
@FLOW 17Y-12
@FLOW 9Y-14-17
@BOX 1.0
CALCULATE CROSSOVER COUNT
FOR CURRENT LINK
@BOX 2.0
FOR EACH LINK
@BOX 3.0
IS LINK SUSPENDED?
@BOX 5.0
LINK TRAVELS TO/FROM
CURRENT COLUMN?
@BOX 6.0
TYPE IS VERTICAL?
@BOX 7.0
CALCULATE XOVER BETWEEN
THIS LINK AND CURRENT
@BOX 8.0
ANY CROSSOVER?
@BOX 9.0
LINK TRAVELS
TO CURRENT COLUMN?
@BOX 10.0
SELECT SIDE ON WHICH
LINK EXITS FROM COLUMN
@BOX 11.0
INC CROSSOVER COUNT ON
THE SIDE THAT THIS LINK LIES
INCLUDE DEST OF THIS LINK
IN THE DESTINATION LIST
@BOX 12.0
END FOR
@BOX 13.0
END
@BOX 14.0
SELECT SIDE ON WHICH
LINK ENTERS COLUMN
@BOX 15.0
CALCULATE VERTICAL INTERSECTIONS
[DOC04.5.1.1]
@BOX 16.0
SAVE CURRENT LINK
CLEAR DESTINATION LISTS
AND CROSSOVER COUNTS
@BOX 17.0
IS THE DEST BOX OF THIS
LINK IN THE DESTINATION LIST?
@BOX 18.0
SAVE DESTINATION BOX OF
THIS LINK
@BOX 1.1
CALCULATE.CROSSOVERS: BEGIN;
$IN COUNT,K,DESTK,SK;

@BOX 16.1
0 => DLIST[LEFT] => DLIST[RIGHT]
=> VDLIST[LEFT] => VDLIST[RIGHT];
0 => LRCT[LEFT] => LRCT[RIGHT]
=> VERTCT[LEFT] => VERTCT[RIGHT];
@BOX 2.1
0 => K;
WHILE 1+>K < LINKLIMIT DO
@BOX 3.1
IF 1 <<- K & SUSP /= 0
@BOX 5.1
IF COLD OF LINK[K] /= COLS OF LINK[I] AND
   COLS OF LINK[K] /= COLS OF LINK[I]
@BOX 7.1
INTERSECT(K,I) => COUNT;
@BOX 8.1
IF COUNT = 0
@BOX 18.1
DEST OF LINK[K] => DESTK;
@BOX 6.1
IF SIDE OF LINK[K] = VERT
@BOX 9.1
IF COLD OF LINK[K] = COLS OF LINK[I]
@BOX 10.1
SIDE OF LINK[K] => SK;
@BOX 17.1
IF 1 <<- DESTK & DLIST[SK] /= 0
@BOX 11.1
1 +> LRCT[SK];
1 <<- DESTK ! DLIST[SK];
@BOX 12.1
OD
@BOX 13.1
END
@BOX 14.1
ENTSIDE OF LINK[K] => SK;
@BOX 15.1
#DOC04.5.1.1
@END
@TITLE DOC04.5.1.1(1,6)
@COL 1S-6R-3T-4T-5R-7T-8R-9T-10F
@FLOW 1-6-3-4N-5-7N-8-9-10
@FLOW 4Y-9
@FLOW 7Y-9
@BOX 1.0
VERTICAL INTERSECTIONS
(NOISE COUNT)
@BOX 3.0
FOR EACH SIDE
@BOX 4.0
THIS DEST IN DESTLIST?
@BOX 5.0
INCLUDE DEST IN VDESTLIST
@BOX 6.0
CALCULATE YCOORDS OF
ENTRY AND EXIT OF BOTH LINKS
DECIDE IF ENTRY ENCLOSED
@BOX 7.0
DOES EITHER LINK ENCLOSE
A FIXED ENTRY OF THE OTHER?
@BOX 8.0
INCREMENT NOISE COUNT
@BOX 9.0
END FOR
@BOX 10.0
END
@BOX 1.1
VERTICAL.INTERSECTIONS : BEGIN;
$IN32 YENTI,YENTK;
$IN IENC,J,KENC;

@BOX 6.1
0 => IENC => KENC;
YENTRY(I) => YENTI; YENTRY(K) => YENTK;
IF(YEXIT(K)-YENTI)* (YENTK - YENTI) < 0 THEN
   1 => IENC;
FI
IF(YEXIT(I)-YENTK)*(YENTI-YENTK) < 0 THEN
   1 => KENC;
FI
@BOX 3.1
FOR J < 2 DO
@BOX 4.1
IF 1 <<- DESTK & (DLIST[J]!VDLIST[J]) /= 0
@BOX 5.1
1 <<- DESTK !> VDLIST[J];
@BOX 7.1
IF ECSIDE[J] OF ENT.CT[DEST OF LINK[I]] > 0 AND IENC /= 0
OR ECSIDE[J] OF ENT.CT[DESTK] > 0 AND KENC /= 0
@BOX 8.1
1 +> VERTCT[J];
@BOX 9.1
OD
@BOX 10.1
END
@END
@TITLE DOC04.6(1,6)
@COL 1S-2T-4T-5T-6R-7T-8R-9R-10T-12T-13R-14T-15T-16T-17F
@FLOW 1-2-4Y-5Y-6-7N-8-9-10-12-13Y-14-15-16-17
@FLOW 4N-15
@FLOW 5N-15
@FLOW 7Y-9
@FLOW 12N-14
@FLOW 16Y-2
@BOX 1.0
REMOVE NULL ERRORS
@BOX 2.0
FOR EACH LINK
@BOX 4.0
SOURCE BOX IS NULL?
@BOX 5.0
ENTRY ON SAME AS EXIT?
@BOX 6.0
SAVE DESTINATION NO
@BOX 7.0
ENTRY ON OTHER SIDE?
@BOX 8.0
DECREMENT ENTRYCOUNT OF DEST
ROUTE FLOW TO OTHER SIDE OF
 SELF AND TIDY IT
- WILL NOT BE DRAWN
@BOX 9.0
CLEAR ENTRYCOUNT OF SOURCE
@BOX 10.0
FOR EACH LINK
@BOX 12.0
LINK GOES TO CORRESPONDING SIDE
OF NULL BOX?
@BOX 13.0
RE-ROUTE LINK TO DEST OF NULL BOX
ALTER DEST, TRUEDEST,COLDEST & ENTRYSIDE
INCREMENT ENTRYCOUNT OF NEW DEST
@BOX 14.0
END FOR
@BOX 15.0
END FOR
@BOX 16.0
ANY ERRORS FOUND
@BOX 17.0
END
@BOX 1.1
REMOVE.NULLS:BEGIN;
$IN NOERRORS,DESTI,M,S;
@BOX 2.1
1 => NOERRORS; 0 => I;
WHILE 1+> I < LINKLIMIT DO
@BOX 4.1
IF T OF BOXTAB[SOURCE OF LINK[I]] > NULL
@BOX 5.1
IF ECSIDE[SIDE OF LINK[I]]OF ENT.CT[SOURCE OF LINK[I]] =< 0
@BOX 6.1
0 => NOERRORS;DEST OF LINK[I] => DESTI;
@BOX 7.1
IF ECSIDE[1-SIDE OF LINK[I]]OF ENT.CT[SOURCE OF LINK[I]] /= 0
@BOX 8.1
1 -> ECSIDE[ENTSIDE OF LINK[I]] OF ENT.CT[DESTI];
SOURCE OF LINK[I] => DEST OF LINK[I]; TOP => TIDY OF LINK[I];
COLS OF LINK[I] => COLD OF LINK[I]; 1 - SIDE OF LINK[I] => ENTSIDE OF LINK[I];
@BOX 9.1
0 => ECSIDE[SIDE OF LINK[I]]OF ENT.CT[SOURCE OF LINK[I]];
@BOX 10.1
0 => M;
WHILE 1+>M < LINKLIMIT DO
@BOX 12.1
IF SOURCE OF LINK[I] /= DEST OF LINK[M]OR
SIDE OF LINK[I] /= ENTSIDE OF LINK[M]
@BOX 13.1
SOURCE OF LINK[M] => S;
IF DEST OF LINK[M]=PFLOW.LINK OF BOXTAB[S]THEN
   DESTI => PFLOW.LINK OF BOXTAB[S];
ELSE
   DESTI => SFLOWLINK OF BOXTAB[S];
FI
DESTI => DEST OF LINK[M]=>TRUEDEST OF LINK[M];
COL OF BOXTAB[DESTI] => COLD OF LINK[M];
IF COLS OF LINK[M] < COLD OF LINK[M] THEN
   1 => SIDE OF LINK[M] => CHSIDE OF LINK[M];
ELSE
   0 => SIDE OF LINK[M] => CHSIDE OF LINK[M];
FI
IF COLD OF LINK[M] = COLS OF LINK[M] THEN
   SIDE OF LINK[M] => ENTSIDE OF LINK[M];
ELSE
   1 - SIDE OF LINK[M] => ENTSIDE OF LINK[M];
FI
1 +> ECSIDE[ENT.SIDE OF LINK[I]] OF ENT.CT[DESTI];
@BOX 14.1
OD
@BOX 15.1
OD
@BOX 16.1
IF NOERRORS = 0
@BOX 17.1
END
@END
@TITLE DOC04.7(1,9)
@COL 24T-26T-28T-27T-25R
@COL 1S-2T-3T-4T-5R-6T-7R-8T-9T-10T-11T-12T-13R-14T-15T
@COL 29N-16R-17T-18R-19R-20T-21T-22T-23F
@ROW 6-29
@ROW 24-13
@FLOW 1-2-3-4Y-5-6-7-8-9N-10-11Y-12Y-13-14-15-16-17Y-18-19-20-21-22-23
@FLOW 4N-29-21
@FLOW 9Y-15
@FLOW 11N-14
@FLOW 12N-24Y-26N-28Y-27Y-25-14
@FLOW 24N-14
@FLOW 26Y-25
@FLOW 17N-19
@FLOW 27N-14
@FLOW  28N-14
@BOX 1.0
BREAK UP
@BOX 2.0
FOR EACH SIDE
@BOX 3.0
FOR EACH BOX
@BOX 4.0
>1 ENTRY ON THIS SIDE OF BOX?
@BOX 5.0
CREATE BREAK TABLE [DOC04.7.1]
CREATE COST TABLE [DOC04.7.2]
@BOX 6.0
FOR EVERY SOURCE IN BREAK TABLE
@BOX 7.0
INIT MINIMUM
@BOX 8.0
FOR EACH SOURCE IN BREAK TABLE
@BOX 9.0
LINK ALREADY ROUTED?
@BOX 10.0
FOR EACH BREAKTABLE ENTRY
@BOX 11.0
THIS ENTRY ALREADY PROCESSED?
@BOX 12.0
COST OF THIS ROUTE < MINIMUM?
@BOX 13.0
SAVE ROUTE AND MINIMUM
@BOX 14.0
END FOR
@BOX 15.0
END FOR
@BOX 16.0
LOOK UP CHOSEN DEST BOX
FIND CHOSEN LINK FROM
CURRENT BREAKTAB ENTRY
@BOX 17.0
HAS LINK DEST ALTERED?
@BOX 18.0
ALTER CHOSEN LINK TO
FOLLOW NEW ROUTE IE
ALTER DEST, ENTRYTYPE,
ENTRYSIDE, COLDEST
@BOX 19.0
MARK LINK AS ROUTED
@BOX 20.0
END FOR
@BOX 21.0
END FOR
@BOX 22.0
END FOR
@BOX 23.0
END
@BOX 24.0
COST = MINIMUM
@BOX 26.0
DEST CLOSER TO TRUEDEST?
@BOX 25.0
SAVE ROUTE
@BOX 27.0
SOURCE CLOSER TO TRUE DEST?
@BOX 28.0
SAME DISTANCE?
@BOX 1.1
BREAK.UP.LINKS: BEGIN;
$IN SD,K,MIN,BREAKLIMIT,S,ND,
P,DIST,YE,SP,DP,J;
@BOX 2.1
FOR SD<2 DO
@BOX 3.1
0 => BOXNO;
WHILE 1 +> BOXNO < BOXLIMIT DO
@BOX 4.1
IF ECSIDE[SD] OF ENT.CT
[BOXNO] =< 1
@BOX 5.1
#DOC04.7.1
#DOC04.7.2
@BOX 6.1
0 => K;
WHILE 1+> K < BREAKLIMIT DO
@BOX 7.1
LARGE.NO => MIN;
@BOX 8.1
0 => I;
WHILE 1+>I < BREAKLIMIT DO
@BOX 9.1
IF TAG[I] /= 0
@BOX 10.1
FOR J < BREAKLIMIT DO
@BOX 11.1
IF TAG[J] = 0
@BOX 12.1
IF COST[J*COSTSIZE+I] >= MIN
@BOX 13.1
COST[J*COSTSIZE+I] => MIN;
I => S; J => ND;
@BOX 14.1
OD
@BOX 15.1
OD
@BOX 16.1
NODE OF BREAK[ND] => I;
LNK OF BREAK[S] => P;
@BOX 17.1
IF I = DEST OF LINK[P]
@BOX 18.1
I => DEST OF LINK[P];
EX => ENTYPE OF LINK[P];
COL OF BOXTAB[I] => DP
=> COLD OF LINK[P];
SIDE OF LINK[P] => SP
=> ENTSIDE OF LINK[P];
IF DP /= COLS OF LINK[P] THEN
   1-SP => ENTSIDE OF LINK[P];
FI
@BOX 19.1
1 => TAG[S];
@BOX 20.1
OD
@BOX 21.1
OD
@BOX 22.1
OD
@BOX 23.1
END
@BOX 24.1
IF COST[J*COSTSIZE+I] /= MIN
@BOX 25.1
I => S; J => ND;
@BOX 26.1
IF Y OF BREAK[J] -Y OF
BREAK[ND] => DIST < 0
@BOX 27.1
IF IABS(YCOORD OF BOXTAB[
NODE OF BREAK[I]]-YE)
-IABS(YCOORD OF BOXTAB[
NODE OF BREAK[S]]-YE) >= 0
@BOX 28.1
IF DIST /= 0
@END
@TITLE DOC04.7.1(1,9)
@COL 1S-3R-4R-5T-7T-9R-10R-11T-12R-13F
@FLOW 1-3-4-5-7Y-9-10-11-12-13
@FLOW 7N-11
@BOX 1.0
CREATE BREAK TABLE
@BOX 3.0
SELECT ENTRY 0 IN BREAK TABLE
CALCULATE YENTRY
MARK ENTRY AS PROCESSED
FILL IN NODE, YCOORD AND LINKNO
@BOX 4.0
INIT BREAKNO
@BOX 5.0
FOR EACH LINK NO
@BOX 7.0
LINK FLOWS TO CURRENT
BOX ON CURRENT SIDE AND SOURCE IS IN SAME OR
ADJACENT COLUMN?
@BOX 9.0
SELECT BREAKTAB ENTRY
SET LINK,NODE,YCOORD
MARK ENTRY UNPROCESSED
@BOX 10.0
INCREMENT BREAKNO
@BOX 12.0
SET BREAKLIMIT
@BOX 11.0
END FOR
@BOX 13.0
END
@BOX 1.1
CREATE.BREAK.TABLE: BEGIN;
$IN BREAKNO;
@BOX 3.1
BOXNO => NODE OF BREAK[0]; 1 => TAG[0];
0 => LNK OF BREAK[0] => Y OF BREAK[0];
YCOORD OF BOXTAB[BOXNO] + HT OF BOXTAB[BOXNO] + EXLINK => YE;
@BOX 4.1
1 => BREAKNO;
@BOX 5.1
0 => I;
WHILE 1+>I < LINKLIMIT DO
@BOX 7.1
IF DEST OF LINK[I] /= BOXNO OR ENTSIDE OF LINK[I] /= SD
OR COLS OF LINK[I] -1 > COL OF BOXTAB[BOXNO] OR COLS OF LINK[I]+1 < COL OF BOXTA
B[BOXNO]
@BOX 9.1
SOURCE OF LINK[I] => NODE OF BREAK[BREAKNO];
I => LNK OF BREAK[BREAKNO];
IABS(YEXIT(I)-YE) => Y OF BREAK[BREAKNO];
0 => TAG[BREAKNO];
@BOX 10.1
1 +> BREAKNO;
@BOX 11.1
OD
@BOX 12.1
BREAKNO => BREAKLIMIT;
@BOX 13.1
END
@END
@TITLE DOC04.7.2(1,9)
@COL 1S-18R-2T-3T-4R-7R-10R-11T-19T-12R-13T-14R-15T-9R-16T-17F
@FLOW 1-18-2-3-4-7-10-11-19N-12-13-14-15-9-16-17
@FLOW 19Y-13
@BOX 1.0
CREATE COST TABLE
@BOX 2.0
FOR EACH ENTRY IN BREAK TABLE
@BOX 3.0
FOR ALL LATER ENTRIES IN BREAK TABLE
@BOX 4.0
INIT COUNT
@BOX 7.0
SELECT LINK ENTRY 0 AND
INIT A LINK BETWEEN THE NODES
OF THESELECTED BREAKTAB ENTRIES
CONSISTING OF SOURCE,SIDE,SOURCE COL,
BOTTOM EXIT,DEST AND DEST COL
@BOX 9.0
SET ENTRYTYPE OF CREATED LINK
TO EXIT
@BOX 10.0
CALCULATE ENTRYSIDE
@BOX 11.0
FOR EACH LINK
@BOX 12.0
INCREASE COUNT BY INTERSECTION
OF LINK AND CREATED LINK
@BOX 13.0
END FOR
@BOX 14.0
STORE COUNT IN BOTH
COST TABLE ENTRIES
@BOX 15.0
ENDFOR
@BOX 16.0
END FOR
@BOX 17.0
END
@BOX 18.0
ENTRYTYPE OF CREATED LINK
IS ENTRY
@BOX 19.0
CROSSOVER IMPOSSIBLE?
@BOX 1.1
CREATE.COST.TABLE: BEGIN;
$IN K,J,COUNT,JJ,U,V,W,X;
@BOX 18.1
ENTRY => ENTYPE OF LINK[0];
@BOX 2.1
FOR K < BREAKLIMIT-1 DO
@BOX 3.1
K => J;
WHILE 1+> J < BREAKLIMIT DO
@BOX 4.1
0 => COUNT;
@BOX 7.1
LNK OF BREAK[J] => JJ;
SOURCE OF LINK[JJ] => SOURCE OF LINK[0];
COLS OF LINK[JJ] => COLS OF LINK[0];
SIDE OF LINK[JJ] => SIDE OF LINK[0];
BOTEX OF LINK[JJ] => BOTEX OF LINK[0];
COL OF BOXTAB[NODE OF BREAK[K] => DEST OF LINK[0]]
=> COLD OF LINK[0];
BOXNO => TRUEDEST OF LINK[0];
@BOX 10.1
IF COLS OF LINK[0] = COLD OF LINK[0] THEN
   SIDE OF LINK[0] => ENTSIDE OF LINK[0];
ELSE
   1 - SIDE OF LINK[0] => ENTSIDE OF LINK[0];
FI
@BOX 11.1
0 => I;
WHILE 1 +> I < LINKLIMIT DO
@BOX 19.1
COLS OF LINK[0]*2+SIDE OF LINK[0]=>U;
COLD OF LINK[0]*2+ENTSIDE OF LINK[0]=>V;
COLS OF LINK[I]*2+SIDE OF LINK[I]=>W;
COLD OF LINK[I]*2+ENTSIDE OF LINK[I]=>X;
IF 1<<- U!(1<<- V) & (1<<- W!(1<<- X)) = 0
@BOX 12.1
INTERSECT(0,I) +> COUNT;
@BOX 13.1
OD
@BOX 14.1
COUNT => COST[J*COSTSIZE + K] => COST[K*COSTSIZE+J];
@BOX 15.1
OD
@BOX 9.1
EX => ENTYPE OF LINK[0];
@BOX 16.1
OD
@BOX 17.1
END
@END
@TITLE DOC04.8(1,6)
@COL 1S-2T-3T-5T-6T-7T-8T-9T-10R-11T-12R-13T-14T-15F
@FLOW 1-2-3-5N-6Y-7N-8Y-9Y-10-11Y-12-13-14-15
@FLOW 5Y-13
@FLOW 6N-13
@FLOW 7Y-13
@FLOW 8N-13
@FLOW 9N-13
@FLOW 11N-13
@BOX 1.0
TIDY UP
@BOX 2.0
FOR BOTTOM TIDY THEN TOPTIDY
@BOX 3.0
FOR EACH LINK
@BOX 5.0
COLUMNAL LINK?
@BOX 6.0
ENTRYTYPE = ENTRY?
@BOX 7.0
ENTRY ABOVE EXIT?
@BOX 8.0
TIDY STATUS < ATTEMPTED TIDY?
@BOX 9.0
TOP TIDY OR BOTTOM EXIT?
@BOX 10.0
SCAN FOR SPACE FOR TIDY
[DOC04.8.1]
@BOX 11.0
ANY SPACE?
@BOX 12.0
ATTEMPTED TIDY
IS SUCCESSFUL
@BOX 13.0
END FOR
@BOX 14.0
END FOR
@BOX 15.0
END
@BOX 1.1
TIDY.UP: BEGIN;
$IN J,FREE;
@BOX 2.1
BOTTOM => J;
WHILE J >= TOP DO
@BOX 3.1
0 => I;
WHILE 1+>I < LINKLIMIT DO
@BOX 5.1
IF COLS OF LINK[I] = COLD OF LINK[I]
@BOX 6.1
IF ENTYPE OF LINK[I] /= ENTRY
@BOX 7.1
IF YENTRY(I) >= YEXIT(I)
@BOX 8.1
IF TIDY OF LINK[I] >= J
@BOX 9.1
IF J /= TOP AND BOTEX OF LINK[I] /= 1
@BOX 10.1
#DOC04.8.1
@BOX 11.1
IF FREE = 0
@BOX 12.1
J => TIDY OF LINK[I];
@BOX 13.1
OD
@BOX 14.1
1 -> J;
OD
@BOX 15.1
END
@END

@TITLE DOC04.8.1(1,6)
@COL 1S-2R-3R-5T-6R-7R-8T-9R-10R-11F
@COL 12R
@ROW 6-12
@FLOW 1-2-3-5N-6-7-8Y-9-10-11
@FLOW 5Y-12-7
@FLOW 8N-10
@BOX 1.0
SPACE FOR TIDY
@BOX 2.0
ASSUME SPACE EXISTS
@BOX 3.0
CALCULATE YCOORDS OF
TOP AND BOTTOM OF LINK
@BOX 5.0
BOTTOM TIDY?
@BOX 6.0
TIDY IN DEST COLUMN
EXCLUDE DEST POINT
@BOX 7.0
SCAN COLUMN FOR
ANY ALLOCATED SPACE
@BOX 8.0
SPACE EXISTS AND BOTTOM TIDY?
@BOX 9.0
ALLOCATE THE SPACE
@BOX 10.0
SET UP RESULT
@BOX 11.0
END
@BOX 12.0
TIDY IN SOURCE COLUMN
EXCLUDE EXIT POINT
@BOX 1.1
SPACE.FOR.TIDY: BEGIN;
$IN YA,YB,K,N;
@BOX 2.1
1 => FREE;
@BOX 3.1
YEXIT(I) => YB; YENTRY(I) => YA;
@BOX 5.1
IF J = BOTTOM
@BOX 6.1
COLD OF LINK[I] => K; 1 +> YA;
@BOX 7.1
YA -1 => N;
WHILE 1+>N =< YB DO
   ALLOC[N] ->> K -= 1 &> FREE;
OD
@BOX 8.1
IF FREE = 0 OR J /= BOTTOM
@BOX 9.1
YA -1 => N;
WHILE 1+>N =< YB DO
   1 <<- K !> ALLOC[N];
OD
@BOX 10.1
:: RESULT IS FREE
@BOX 11.1
END
@BOX 12.1
COLS OF LINK[I] => K; 1 -> YB;
@END

@TITLE DOC04.9(1,6)
@COL 15A
@COL 1S-12T-3T-4R-5T-7T-8R-9T-10T-11R-16T-13T-14F
@ROW 15-5
@FLOW 1-12-3-4-5-7Y-8-9-10Y-11-16-13-14
@FLOW 7N-9-10N-16
@BOX 1.0
PROCESS COLUMNAL LINKS
@BOX 3.0
FOR EACH SIDE
@BOX 4.0
NO LINK NO'S SELECTED
INITIALISE MINIMUM CHANNEL
@BOX 5.0
FOR EACH LINK
@BOX 7.0
DEST IN CORRECT COL
ON CORRECT SIDE AND
LINK NEITHER TIDIED NOR
ALREADY ALLOCATED?
@BOX 8.0
INCLUDE LINKNO
IN SELECTED SET
@BOX 9.0
END FOR
@BOX 10.0
ANY LINKNOS SELECTED?
@BOX 11.0
CALCULATE NEST COUNTS,
OVERLAP SETS AND
ENCLOSURE SETS
[DOC04.9.1]
ALLOCATE CHANNELS
[DOC04.9.2]
@BOX 12.0
FOR EACH COLUMN
@BOX 13.0
END FOR
@BOX 14.0
END
@BOX 15.0
LATER-
CHECK FOR COLUMNAL LINK
@BOX 16.0
END FOR
@BOX 1.1
PROCESS.COLUMNAL.LINKS: BEGIN;
$IN SD,MINCHAN;
$LO64 SELECTED;
@BOX 12.1
FOR COLNO < COLIMIT DO
@BOX 3.1
FOR SD < 2 DO
@BOX 4.1
MAXCHAN => MINCHAN; 0 => SELECTED;
@BOX 5.1
0 => I;
WHILE 1+>I < LINKLIMIT DO
@BOX 7.1
IF COLD OF LINK[I] /= COLNO OR ENTSIDE OF LINK[I] /= SD
OR TIDY OF LINK[I] /= NONE OR CHAN OF LINK[I] /= 0
@BOX 8.1
1 <<- I !> SELECTED;
@BOX 9.1
OD
@BOX 10.1
IF SELECTED = 0
@BOX 11.1
#DOC04.9.1
#DOC04.9.2
@BOX 16.1
OD
@BOX 13.1
OD
@BOX 14.1
END
@END
@TITLE DOC04.9.1(1,6)
@COL 25A-18R-20R
@COL 22R-24R
@COL 1S-2T-3T-26R-4T-5T-6T-8T-9T-11R-13R-14T-15T-16F
@ROW 25-2
@ROW 18-22-9
@FLOW 1-2-3Y-26-4-5Y-6N-8N-9Y-11-13-14-15-16
@FLOW 3N-15
@FLOW 5N-14
@FLOW 6Y-18-20-14
@FLOW 8Y-22-24-14
@FLOW 9N-14
@BOX 1.0
CALCULATE NEST COUNT ETC
@BOX 2.0
FOR ALL LINKS BUT THE LAST
@BOX 3.0
IS LINK SELECTED?
@BOX 4.0
FOR ALL LATER ENTRIES IN LINK TABLE
@BOX 5.0
IS THE LINK SELECTED?
@BOX 6.0
THE LINKS HAVE CO-EXISTING PATHS?
@BOX 8.0
FIRST LINK ENCLOSES SECOND?
@BOX 9.0
SECOND LINK ENCLOSES FIRST?
@BOX 11.0
SELECT SECOND LINK
UPDATE NEST COUNT
@BOX 13.0
SELECT FIRST LINK
UPDATE ENCLOSURE
@BOX 14.0
END FOR
@BOX 15.0
END FOR
@BOX 16.0
END
@BOX 18.0
SELECT FIRST LINK
UPDATE OVERLAP AND NEST COUNT
@BOX 20.0
SELECT SECOND LINK
UPDATE OVERLAP AND NEST COUNT
@BOX 22.0
SELECT FIRST LINK
UPDATE NEST COUNT
@BOX 24.0
SELECT SECOND LINK
UPDATE ENCLOSURE
@BOX 25.0
NOTE:-
THIS LOOP MAY EXIT
IMMEDIATELY
@BOX 26.0
CALCULATE YCOORDS
OF LINK
@BOX 1.1
CALC.NEST.COUNT: BEGIN;
$IN J;
$IN YA,YB,YD,YE;
@BOX 2.1
0 => I;
WHILE 1+>I < LINKLIMIT - 1 DO
@BOX 3.1
IF 1 <<- I & SELECTED = 0
@BOX 26.1
YEXIT(I) => YA; YENTRY(I) => YB;
@BOX 4.1
I => J;
WHILE 1 +> J < LINKLIMIT DO
@BOX 5.1
IF 1 <<- J & SELECTED = 0
@BOX 6.1
YEXIT(J) => YD; YENTRY(J) => YE;
IF(YA-YE)-=(YB-YE)-=(YA-YD)-=(YB-YD) < 0
@BOX 8.1
IF(YA-YD)*(YB-YD) =< 0 AND
  (YA-YE)*(YB-YE) =< 0
@BOX 9.1
IF(YD-YA)*(YE-YA) > 0 OR
  (YD-YB)*(YE-YB) > 0
@BOX 11.1
2 +> NCT OF LINK[J];
@BOX 13.1
1 <<- J !> ENCLOSURE OF LINK[I];
@BOX 14.1
OD
@BOX 15.1
OD
@BOX 16.1
END
@BOX 18.1
1 +> NCT OF LINK[I];
1 <<- J !> OVERLAP OF LINK[I];
@BOX 20.1
1 +> NCT OF LINK[J];
1 <<- I !> OVERLAP OF LINK[J];
@BOX 22.1
2 +> NCT OF LINK[I];
@BOX 24.1
1 <<- I !> ENCLOSURE OF LINK[J];
@END
@TITLE DOC04.9.2(1,6)
@COL 1S-2R-3R-4T-5T-7T-8T-9T-10T-11R-12T-13R-14T-15R-16F
@COL 18R
@COL 17R
@ROW 11-18-17
@FLOW 1-2-3-4-5Y-7N-8N-9N-10Y-11-12-13-14Y-15-16
@FLOW 8Y-17-12
@FLOW 9Y-18-12
@FLOW 10N-12
@FLOW 5N-12
@FLOW 7Y-12
@FLOW 14N-3
@BOX 1.0
ALLOCATE CHANNELS
@BOX 2.0
INITIALISE LINK GROUP CHANNELS
@BOX 3.0
INITIALISE SHARELINK, MAXNC
MAXLINK AND LEVELLINK
@BOX 4.0
FOR EACH LINK
@BOX 5.0
IS LINK SELECTED?
@BOX 7.0
IS LINK ENCLOSED?
@BOX 8.0
SHARE CHANNEL WITH BOUNDARY?
@BOX 9.0
USE LINKGROUP CHANNEL?
@BOX 10.0
LARGEST NEST COUNT SO FAR?
@BOX 11.0
SAVE MAXLINK.NOTE MAX NESTCOUNT
@BOX 12.0
END FOR
@BOX 13.0
ALLOCATE CHANNELS(CONT)
[DOC04.9.2.1]
@BOX 14.0
SELECTED IS EMPTY?
@BOX 15.0
SAVE MIN CHANNEL NO
@BOX 16.0
END
@BOX 17.0
SAVE SHARELINK
@BOX 18.0
SAVE LEVELLINK
@BOX 1.1
ALLOCATE.CHANNELS: BEGIN;
$IN MAXNC,SHARELINK,LEVELINK,MAXLINK,Q,J;

@BOX 2.1
FOR BOXNO < BOXLIMIT DO
   MAXCHAN => LGCNO[BOXNO];
OD
@BOX 3.1
-1 => MAXNC; 0 => SHARELINK => LEVELINK => MAXLINK;
@BOX 4.1
0 => I;
WHILE 1+>I < LINKLIMIT DO
@BOX 5.1
IF 1 <<- I & SELECTED = 0
@BOX 7.1
IF ENCLOSURE OF LINK[I] /= 0
@BOX 8.1
IF BLDEST OF LINK[I] = TRUEDEST OF LINK[I]
@BOX 9.1
IF LGCNO[TRUEDEST OF LINK[I]] < BCHAN OF LINK[I]
@BOX 10.1
IF NCT OF LINK[I] =< MAXNC
@BOX 11.1
I => MAXLINK; NCT OF LINK[I] => MAXNC;
@BOX 12.1
OD
@BOX 13.1
#DOC04.9.2.1
@BOX 14.1
IF SELECTED /= 0
@BOX 15.1
MINCHAN => SID[SD] OF MINC[COLNO];
@BOX 16.1
END
@BOX 17.1
I => SHARELINK;
@BOX 18.1
I => LEVELINK;
@END
@TITLE DOC04.9.2.1(1,6)
@COL 28N-20R-19R
@COL 1S-2T-3R-4R-5T-6T-7R-9R-10R-11T-12T-14T-15R-16R-17T-18F
@COL 21T-22R-24R-25R-27R
@ROW 28-5
@ROW 20-7
@ROW 3-21
@ROW 29-9-25
@FLOW 1-2Y-3-4-5N-6N-7-9-10-11-12Y-14Y-15-16-17-18
@FLOW 2N-21Y-22-24-9
@FLOW 21N-25-27-9
@FLOW 5Y-28-19-9
@FLOW 6Y-20-9
@FLOW 12N-17
@FLOW 14N-17
@BOX 1.0
ALLOCATE CHANNELS(CONT)
@BOX 2.0
BOUNDARY SHARING POSSIBLE?
@BOX 3.0
SAVE LINK
@BOX 4.0
SELECT LINK ENTRY
SET CHAN TO BOUNDARY
@BOX 5.0
ENTRYTYPE = EXIT?
@BOX 6.0
BOUNDARY ENTRYTYPE
IS EXIT?
@BOX 7.0
RE-ROUTE BOUNDARY
TO SOURCE OF LINK
@BOX 9.0
SELECT LINK ENTRY
NOTE CHANNEL AS MINCHAN
UPDATE LINK GROUP CHANNEL
@BOX 10.0
DE-SELECT LINKNO
@BOX 11.0
FOR EACH LINK
@BOX 12.0
LINKNO SELECTED?
@BOX 14.0
ENCLOSED BY OR
OVERLAPS NEWLY
POSITIONED LINK
@BOX 15.0
UPDATE BOUNDARY CHANNEL
BOUNDARY LINK, BOUNDARY DEST
@BOX 16.0
REMOVE NEWLY POSND
LINK FROM ENCLOSURE
@BOX 17.0
END FOR
@BOX 18.0
END
@BOX 19.0
RE-ROUTE LINK TO
BOUNDARY DEST
RE-ROUTE BOUNDARY
TO LINK SOURCE
@BOX 20.0
RE-ROUTE BOUNDARY
TO DEST OF LINK
@BOX 21.0
LINK GROUP CHANNEL?
@BOX 22.0
SAVE LINK
@BOX 24.0
SELECT LINK ENTRY
SET CHANNEL
FROM LINK GROUP
@BOX 25.0
SAVE LINK
@BOX 27.0
SELECT LINK ENTRY
SET CHANNEL
INSIDE BOUNDARY
@BOX 1.1
ALLOC.CHANS.CONT: BEGIN;

@BOX 2.1
IF SHARELINK = 0
@BOX 3.1
SHARELINK => I;
@BOX 4.1
BLINK OF LINK[I] => Q;
BCHAN OF LINK[I] => CHAN OF LINK[I];
@BOX 5.1
IF ENTYPE OF LINK[I] = EX
@BOX 6.1
IF ENTYPE OF LINK[Q] = EX
@BOX 7.1
SOURCE OF LINK[I] => DEST OF LINK[Q];
COLS OF LINK[I] => COLD OF LINK[Q];
EX => ENTYPE OF LINK[Q];
SIDE OF LINK[I] => ENTSIDE OF LINK[Q];
@BOX 9.1
SD => CHSIDE OF LINK[I];
 COLNO => COLC OF LINK[I];
IF CHAN OF LINK[I] < MINCHAN THEN
   CHAN OF LINK[I] => MINCHAN;
FI CHAN OF LINK[I] =>
 LGCNO[TRUEDEST OF LINK[I]];
@BOX 10.1
1 <<- I -= %F(16) &> SELECTED;
@BOX 11.1
0 => J;
WHILE 1+>J < LINKLIMIT DO
@BOX 12.1
IF 1 <<- J & SELECTED = 0
@BOX 14.1
IF 1 <<- I &(OVERLAP OF LINK[J]
 !ENCLOSURE OF LINK[J]) = 0
@BOX 15.1
CHAN OF LINK[I] => BCHAN OF LINK[J];
I => BLINK OF LINK[J];
TRUEDEST OF LINK[I] => BLDEST OF LINK[J];
@BOX 16.1
1 <<- I -= %F(16) &> ENCLOSURE OF LINK[J];
@BOX 17.1
OD
@BOX 18.1
END
@BOX 19.1
DEST OF LINK[Q] => DEST OF LINK[I];
ENTYPE OF LINK[Q] => ENTYPE OF LINK[I];
SOURCE OF LINK[I] => DEST OF LINK[Q];
EX => ENTYPE OF LINK[Q];
COLD OF LINK[Q] => COLD OF LINK[I];
COLS OF LINK[I] => COLD OF LINK[Q];
ENTSIDE OF LINK[Q] => ENTSIDE OF LINK[I];
SIDE OF LINK[I] => ENTSIDE OF LINK[Q];
@BOX 20.1
DEST OF LINK[I] => DEST OF LINK[Q];
ENTYPE OF LINK[I] => ENTYPE OF LINK[Q];
COLD OF LINK[I] => COLD OF LINK[Q];
ENTSIDE OF LINK[I] => ENTSIDE OF LINK[Q];
@BOX 21.1
IF LEVELINK = 0
@BOX 22.1
LEVELINK => I;
@BOX 24.1
LGCNO[TRUEDEST OF LINK[I]] =>
CHAN OF LINK[I];
@BOX 25.1
MAXLINK => I;
@BOX 27.1
BCHAN OF LINK[I] -1 =>
CHAN OF LINK[I];
@END
@TITLE DOC04.11(1,9)
@COL 18R
@COL 1S-2T-3R-5T-6R-7T-8R-9T-10T-11R-12R-13T-14R-15R-16T-17F
@COL 19R-20R-21R
@ROW 18-11-20
@ROW 14-21
@ROW 6-19
@FLOW 1-2-3-5Y-6-7Y-8-9Y-10N-11-12-13Y-14-15-16-17
@FLOW 5N-19-7N-9N-20-12
@FLOW 10Y-18-12
@FLOW 13N-21-15
@BOX 1.0
OUTPUT LINKS
@BOX 3.0
CALCULATE COORDS
OF EXIT AND ENTRY
@BOX 2.0
FOR EACH LINK
@BOX 5.0
BOTTOM EXIT?
@BOX 6.0
USE PRIMARY TEXT
DRAW EXIT STUB UNLESS SOURCE NULL
@BOX 7.0
ANY EXIT TEXT?
@BOX 8.0
DRAW TEXT
@BOX 9.0
TIDY?
@BOX 10.0
TOP TIDY?
@BOX 11.0
CHANNEL IS
SOURCE COLUMN
@BOX 12.0
DRAW LINK TO CHANNEL
@BOX 13.0
ENTRYTYPE IS ENTRY?
@BOX 14.0
ARROW ON LINE
@BOX 15.0
DRAW VERTICAL PART
DRAW LINE TO ENTRY
DRAW ENTRY STUB IF ENTRYTYPE IS
ENTRY AND DEST NOT NULL
@BOX 16.0
END FOR
@BOX 17.0
END
@BOX 18.0
CHANNEL IS
DEST COLUMN
@BOX 19.0
USE SECONDARY EXIT
@BOX 20.0
CALCULATE CHANNEL
X COORDINATE
@BOX 21.0
NO ARROW ON LINE
@BOX 1.1
OUTPUT.LINKS: BEGIN;
$IN XE,XX,YE,YX,S,TT,L,XCHAN,A,COLCI,CHI,CWTH,DISP;
@BOX 2.1
0 => I;
WHILE 1+>I < LINKLIMIT DO
@BOX 3.1
XENTRY(I) => XE; XEXIT(I) => XX;
YENTRY(I) => YE; YEXIT(I) => YX;
2 => DISP;
@BOX 5.1
IF BOTEX OF LINK[I] = 0
@BOX 6.1
IF T OF BOXTAB[SOURCE OF LINK[I]] > NULL THEN
   IF DEVNO = 0 THEN
      DRAWLINE.LPT(XX,YX+STALK,XX,YX,0);
   ELSE
      DRAWLINE.COR(XX,YX+STALK,XX,YX,0);
FI FI
PFLOW.TEXT OF BOXTAB[SOURCE OF LINK[I]] => TT;
2*SIDE OF LINK[I] -: 1 => S;
IF DEVNO < 3 THEN
   0 => DISP;
FI
@BOX 7.1
IF DR.SW&1 /= 0 OR LENGTH(TT) => L = 0
@BOX 8.1
IF DEVNO = 0 THEN
   DRAWTEXT.LPT(^BTB,XX+(S*(L+1)),YX+DISP,TT,1,'-,0);
ELSE
   DRAWTEXT.COR(^BTB,XX+(S*(L+1)),YX+DISP,TT,1,'-,0);
FI
@BOX 9.1
IF TIDY OF LINK[I] = NONE
@BOX 10.1
IF TIDY OF LINK[I] = TOP
@BOX 11.1
COLX[COLS OF LINK[I]] => XCHAN;
@BOX 12.1
IF DEVNO = 0 THEN
   DRAWLINE.LPT(XX,YX,XCHAN,YX,1);
ELSE
   DRAWLINE.COR(XX,YX,XCHAN,YX,1);
FI
@BOX 13.1
IF ENTYPE OF LINK[I] /= ENTRY
@BOX 14.1
ARROW => A;
@BOX 15.1
IF DEVNO = 0 THEN
   DRAWLINE.LPT(XCHAN,YX,XCHAN,YE,A);
   DRAWLINE.LPT(XCHAN,YE,XE,YE,A);
ELSE
   DRAWLINE.COR(XCHAN,YX,XCHAN,YE,A);
   DRAWLINE.COR(XCHAN,YE,XE,YE,A);
FI
IF ENTYPE OF LINK[I]=ENTRY AND
T OF BOXTAB[DEST OF LINK[I]]>NULL THEN
   IF DEVNO = 0 THEN
      DRAWLINE.LPT(XE,YE,XE,YE-STALK,0);
   ELSE
      DRAWLINE.COR(XE,YE,XE,YE-STALK,0);
FI FI
@BOX 16.1
OD
@BOX 17.1
END
@BOX 18.1
COLX[COLD OF LINK[I]]
 => XCHAN;
@BOX 19.1
2 * SIDE OF LINK[I] -1 => S;
SFLOW.TEXT OF BOXTAB
[SOURCE OF LINK[I]] => TT;
@BOX 20.1
COLWTH[COLC OF LINK[I]=>COLCI]
=>CWTH;
CHSIDE OF LINK[I]=>CHI;
CHAN OF LINK[I] - SID[CHI]
 OF MINC[COLCI]+1*2+CWTH
*(CHI*2-1)+COLX[COLCI]=>XCHAN;
@BOX 21.1
NOARROW => A;
@END
@TITLE DOC04.12(1,9)
@COL 1S-2T-18T-3R-6T-11T-13T-14R-12R-15T-16F
@COL 7T-8R-9T-10R
@ROW 11-7
@FLOW 1-2-18Y-3-6Y-7Y-8-9Y-10-11N-13Y-14-12-15-16
@FLOW 9N-11
@FLOW 6N-11Y-12
@FLOW 13N-12
@FLOW 7N-11
@FLOW 18N-15
@BOX 1.0
OUTPUT BOXES
@BOX 2.0
FOR EVERY BOX
@BOX 3.0
LOOK UP NO
OF LINES IN BOX
LOOK UP COORD
OF BOX
@BOX 6.0
ANY PRIMARY FLOW?
@BOX 7.0
TO BOX BELOW?
@BOX 8.0
OUTPUT FLOWLINE
@BOX 9.0
LEVEL 0 WITH
A PRIMARY TEXT?
@BOX 10.0
OUTPUT TEXT
@BOX 11.0
BOXTYPE = NULL?
@BOX 12.0
OUTPUT BOX SHAPE
@BOX 13.0
ANY INTERNAL TEXT?
@BOX 14.0
OUTPUT TEXT
@BOX 15.0
END FOR
@BOX 16.0
END
@BOX 18.0
TYPE ASSIGNED?
@BOX 1.1
OUTPUT.BOXES: BEGIN;
$IN Q,NOLS,XE,L,YX,YE,TT,I,J,K,DISP1,DISP2,TYP;
@BOX 2.1
FOR BOXNO < BOXLIMIT DO
@BOX 18.1
IF T OF BOXTAB[BOXNO] => TYP = UNDEF
@BOX 3.1
BOXHT OF BOXTAB[BOXNO] => NOLS;
COLX[COL OF BOXTAB[BOXNO]] => XE;
@BOX 6.1
IF PFLOW.LINK OF BOXTAB[BOXNO] => Q /= 0
@BOX 7.1
IF Q /= COL.LINK OF BOXTAB[BOXNO]
@BOX 8.1
YCOORD OF BOXTAB[BOXNO]-HT OF BOXTAB[BOXNO]=> YX;
YCOORD OF BOXTAB[Q] + HT OF BOXTAB[Q]=> YE;
EXLINK-STALK => DISP1 => DISP2;
IF TYP = NULL THEN
   0 => DISP1;
FI
IF T OF BOXTAB[Q] = NULL THEN
   0 => DISP2;
FI
IF DEVNO = 0 THEN
   DRAWLINE.LPT(XE,YX-DISP1,XE,YE+DISP2,1);
ELSE
   DRAWLINE.COR(XE,YX-DISP1,XE,YE+DISP2,1);
FI
@BOX 9.1
IF DR.SW&1 /= 0 OR
 LENGTH(PFLOW.TEXT OF BOXTAB[BOXNO]=>TT) => L = 0
@BOX 10.1
IF DEVNO = 0 THEN
   DRAWTEXT.LPT(^BTB,XE+L+1,YX-2,TT,1,'-,0);
ELSE
   DRAWTEXT.COR(^BTB,XE+L+1,YX-2,TT,1,'-,0);
FI
@BOX 11.1
IF TYP = NULL
@BOX 12.1
IF DEVNO = 0 THEN
   DRAWSHAPE.LPT(BOXNO);
ELSE
   DRAWSHAPE.COR(BOXNO);
FI
@BOX 13.1
IF TEXT.PTR OF BOXTAB[BOXNO] => TT = 0 OR NOLS = 0
@BOX 14.1
IF DEVNO = 0 THEN
   DRAWTEXT.LPT(^BTB,XE,YCOORD OF BOXTAB[BOXNO],TT,NOLS,EOBWC,0);
ELSE
   DRAWTEXT.COR(^BTB,XE,YCOORD OF BOXTAB[BOXNO],TT,NOLS,EOBWC,0);
FI
@BOX 15.1
OD
@BOX 16.1
END
@END
@TITLE DOC04.13(1,6)
@COL 1S-3T-4R-5F
@COL 6R
@ROW 4-6
@FLOW 1-3N-4-5
@FLOW 3Y-6-5
@BOX 1.0
SUBROUTINE XEXIT(LINKNO)
@BOX 3.0
BOTTOM EXIT?
@BOX 4.0
XCOORD OF COLUMN
+ OR - BOXWIDTH
@BOX 5.0
RETURN
@BOX 6.0
XCOORD OF COLUMN
@BOX 1.1
PROC XEXIT(L);

@BOX 3.1
IF BOTEX OF LINK[L] /= 0
@BOX 4.1
SIDE OF LINK[L]*2 -1 *BOXWTH
OF BOXTAB[SOURCE OF LINK[L]]+
COLX[COLS OF LINK[L]] => XEXIT;
@BOX 5.1
END
@BOX 6.1
COLX[COLS OF LINK[L]] => XEXIT;
@END
@TITLE DOC04.14(1,9)
@COL 1S-7T-3T-4R-5F
@COL 6R
@ROW 4-6
@FLOW 1-7N-3N-4-5
@FLOW 3Y-6-5
@FLOW 7Y-4
@BOX 1.0
SUBROUTINE YEXIT(LINKNO)
@BOX 3.0
BOTTOM EXIT?
@BOX 4.0
YCOORD OF BOX
@BOX 5.0
RETURN
@BOX 6.0
YCOORD - BOXHEIGHT -EXLINK
@BOX 7.0
NULL SOURCE BOX?
@BOX 1.1
PROC YEXIT(L);
$IN YX;
@BOX 3.1
IF BOTEX OF LINK[L] /= 0
@BOX 4.1
YCOORD OF BOXTAB[SOURCE OF LINK[L]] => YX => YEXIT;
IF DEVNO > 2 THEN
   YX / 2 * 2 +1 => YEXIT;
FI
@BOX 5.1
END
@BOX 6.1
YCOORD OF BOXTAB[SOURCE OF LINK[L]]-
HT OF BOXTAB[SOURCE OF LINK[L]] -EXLINK => YEXIT;
@BOX 7.1
IF T OF BOXTAB[SOURCE OF LINK[L]] =< NULL
@END
@TITLE DOC04.15(1,6)
@COL 1S-3T-7T-4R-5F
@COL 6R
@ROW 4-6
@FLOW 1-3N-7N-4-5
@FLOW 3Y-6-5
@FLOW 7Y-6
@BOX 1.0
SUBROUTINE XENTRY(LINKNO)
@BOX 3.0
ENTRYTYPE = ENTRY?
@BOX 4.0
XCOORD OF DEST COL
+ OR - WIDTH OF DEST BOX
@BOX 5.0
EXIT
@BOX 6.0
XCOORD OF DEST COL
@BOX 7.0
TRUEDEST OF LINK=
PRIMARY OF DEST BOX?
@BOX 1.1
PROC XENTRY(L);
@BOX 3.1
IF ENTYPE OF LINK[L] = ENTRY
@BOX 4.1
ENTSIDE OF LINK[L] *2 -1 * BOXWTH OF
BOXTAB[DEST OF LINK[L]] + COLX[COLD
OF LINK[L]] => XENTRY;
@BOX 5.1
END
@BOX 6.1
COLX[COLD OF LINK[L]] => XENTRY;
@BOX 7.1
IF TRUEDEST OF LINK[L] = PFLOW.LINK OF
BOXTAB[DEST OF LINK[L]]
@END
@TITLE DOC04.16(1,9)
@COL 8R
@COL 1S-9T-3T-7T-4R-5F
@COL 6R
@ROW 8-4-6
@FLOW 1-9N-3N-7N-4-5
@FLOW 3Y-6-5
@FLOW 7Y-8-5
@FLOW 9Y-4
@BOX 1.0
SUBROUTINE YENTRY(LINKNO)
@BOX 3.0
ENTRYTYPE = ENTRY?
@BOX 4.0
USE YCOORD OF DEST BOX
@BOX 5.0
RETURN
@BOX 6.0
YCOORD OF DEST BOX
+ HEIGHT + ENTRY LINK
@BOX 7.0
TRUEDEST  OF LINK =
PRIMARY OF DEST BOX?
@BOX 8.0
YCOORD OF DESTBOX
-HEIGHT-ENTRY LINK
@BOX 9.0
NULL DEST BOX?
@BOX 1.1
PROC YENTRY(L);
$IN DST,YE;
@BOX 3.1
IF ENTYPE OF LINK [L] = ENTRY
@BOX 4.1
YCOORD OF BOXTAB[DST] => YE => YENTRY;
IF DEVNO > 2 THEN
   YE / 2 * 2 + 1 => YENTRY;
FI
@BOX 5.1
END
@BOX 6.1
YCOORD OF BOXTAB[DST] + HT OF
BOXTAB[DST]+EXLINK => YENTRY;
@BOX 7.1
IF TRUEDEST OF LINK[L]=
PFLOW.LINK OF BOXTAB[DST]
@BOX 8.1
YCOORD OF BOXTAB[DST] - HT OF
BOXTAB[DST] -EXLINK => YENTRY;
@BOX 9.1
IF T OF BOXTAB[DEST OF
LINK[L] => DST] =< NULL
@END
@TITLE DOC04.17(1,6)
@COL 1S-2R-3T-5T-6R-7R-8F
@FLOW 1-2-3Y-5N-6-5Y-7-8
@FLOW 3N-7
@BOX 1.0
LENGTH SUBROUTINE
@BOX 2.0
SAVE INDEX
@BOX 3.0
VALID TEXT INDEX?
@BOX 5.0
END OF CAPTION TEXT?
@BOX 6.0
INCREMENT INDEX
@BOX 7.0
RESULT IS
INDEX - SAVED INDEX
@BOX8.0
END
@BOX 1.1
PROC LENGTH(TX);
$IN START;
@BOX 2.1
TX => START;
@BOX 3.1
IF TX = 0
@BOX 5.1
IF BTB[TX] = '-
@BOX 6.1
1 +> TX;
@BOX 7.1
TX - START => LENGTH;
@BOX 8.1
END
@END
@TITLE DOC04.19(1,6)
@COL 11R
@COL 1S-2R-3T-4R-5R-6T-7R-8T-9R-10F
@COL 12R
@COL 13R
@ROW 11-9-12-13
@FLOW 1-2-3N-4-5-6N-7-8N-9-10
@FLOW 3Y-13-10
@FLOW 6Y-12-10
@FLOW 8Y-11-10
@BOX 1.0
INTERSECTION
@BOX 2.0
CALCULATE YCOORDS
OF LINK ENDS
@BOX 3.0
BOTH LINKS TO
AND FROM SAME COL?
@BOX 4.0
LOOK UP X COORDS
OF LINK ENDS
@BOX 5.0
EVALUATE COMPLEX
INTERSECTION EXPR 1
@BOX 6.0
EXPRESSION > 0?
@BOX 7.0
EVALUATE COMPLEX
INTERSECTION EXPR 2
@BOX 8.0
EXPRESSION > 0?
@BOX 9.0
INTERSECTION UNLESS
SUM OF EXPR'S = 0
@BOX 10.0
EXIT
@BOX 11.0
NO INTERSECTION
@BOX 12.0
NO INTERSECTION
@BOX 13.0
SIMPLE INTERSECTION
EVALUATION
@BOX 1.1
PROC INTERSECT(A,B);
$IN32 X1,X2,X3,X4,Y1,Y2,Y3,Y4,E1,E2;
@BOX 2.1
YEXIT(A) => Y1; YENTRY(A) => Y2;
YEXIT(B) => Y3; YENTRY(B) => Y4;
@BOX 3.1
IF COLS OF LINK[A] = COLD OF LINK[A]
AND COLD OF LINK[B] = COLS OF LINK[B]
AND COLS OF LINK[B] = COLS OF LINK[A]
@BOX 4.1
COLX[COLS OF LINK[A]] => X1;
COLX[COLD OF LINK[A]] => X2;
COLX[COLS OF LINK[B]] => X3;
COLX[COLD OF LINK[B]] => X4;
@BOX 5.1
((X2-X1)*(Y3-Y1)-((X3-X1)*(Y2-Y1)))*
((X2-X1)*(Y4-Y1)-((X4-X1)*(Y2-Y1))) => E1;
@BOX 6.1
IF E1 > 0
@BOX 7.1
((X4-X3)*(Y1-Y3)-((X1-X3)*(Y4-Y3)))*
((X4-X3)*(Y2-Y3)-((X2-X3)*(Y4-Y3))) => E2;
@BOX 8.1
IF E2 > 0
@BOX 9.1
IF E1 = 0 AND E2 = 0 THEN
   0 => INTERSECT;
ELSE
   1 => INTERSECT;
FI
@BOX 10.1
END
@BOX 11.1
0 => INTERSECT;
@BOX 12.1
0 => INTERSECT;
@BOX 13.1
IF((Y1-Y3)*(Y2-Y3)*(Y1-Y4)*(Y2-Y4)) < 0 THEN
   1 => INTERSECT;
ELSE
   0 => INTERSECT;
FI
@END

