-- ALEPress.mesa 
--    Edited by Sweet, 28-May-85 12:25:30

DIRECTORY
  ALEOps,
  Inline,
  IODefs,
  PressDefs,
  Storage,
  StreamDefs,
  String;

ALEPress: PROGRAM IMPORTS 
    ALEOps, Inline, IODefs, PressDefs, Storage, StreamDefs, String 
  EXPORTS ALEOps =
  BEGIN OPEN ALEOps;


  marginX: Mica = 2540/4;
  marginY: Mica = -2540/2;
  PageTop: Mica = 2540 * 11;

  scaleDen: CARDINAL ← 16;
  Mica: TYPE = INTEGER;
  singleWidth: Mica ← 30;

  Sqrt: PUBLIC PROC [n: LONG CARDINAL] RETURNS [r: CARDINAL] =
    BEGIN
    r1: CARDINAL;
    r ← 1;
    DO
      r1 ← (r + Inline.LongDiv[n, r])/2;
      IF r1 = r THEN EXIT;
      r ← r1;
      ENDLOOP;
    END;
   
  maxPerCmd: CARDINAL ← 30; 
  JamPicture: PUBLIC PROC [file: STRING] = 
    BEGIN OPEN StreamDefs;
    js: DiskHandle;
    cmdNum: CARDINAL ← 1;
    thisCmd: CARDINAL ← 0;
    Another: PROC = 
      BEGIN
      IF thisCmd >= maxPerCmd THEN
        BEGIN
	cmdNum ← cmdNum+1;
	OutS["}.cvx .def

(draw-picture-"]; OutN[cmdNum];
	OutS[") {
"];
	END;
      END;
    OutS: PROC [s: STRING] = 
      BEGIN
      FOR i: CARDINAL IN [0..s.length) DO
        js.put[js, s[i]];
	ENDLOOP;
      END;
    OutC: PROC [c: CHARACTER] =
      BEGIN
      js.put[js, c];
      END;
    OutN: PROC [n: CARDINAL] =
      BEGIN
      IODefs.OutNumber[js, n, 
        [base: 10, zerofill: FALSE, unsigned: TRUE, columns: 1]];
      END;
    OutF: PROC [f: CARDINAL] = 
      BEGIN
      SELECT f FROM
        0 => NULL;
	1 => OutS[".0625"];
	2 => OutS[".125"];
	3 => OutS[".1875"];
	4 => OutS[".25"];
	5 => OutS[".3125"];
	6 => OutS[".375"];
	7 => OutS[".4375"];
	8 => OutS[".5"];
	9 => OutS[".5625"];
	10 => OutS[".625"];
	11 => OutS[".6875"];
	12 => OutS[".75"];
	13 => OutS[".8125"];
	14 => OutS[".876"];
	15 => OutS[".9375"];
	16 => OutS["1.0"];
	ENDCASE;
      END;
    OutD: PROC [ac: ADistance] =
      BEGIN
      f: CARDINAL;
      IF ac < 0 THEN {OutC['-]; ac ← -ac};
      f ← CARDINAL[Inline.LowHalf[ac]] MOD 16;
      ac ← ac / 16;
      IODefs.OutNumber[js, Inline.LowHalf[ac], 
        [base: 10, zerofill: FALSE, unsigned: TRUE, columns: 1]];
      OutF[f];
      END;
    clw: INTEGER ← -1;
    box: ABox ← [x1: 0, x2: LAST[ADistance], y1: 0, y2: LAST[ADistance]];
    JamLabel: LabelScan =
      BEGIN
      labelString: STRING ← [100];
      stringCommand: ARRAY FontSize OF ARRAY LabelMode OF STRING ← [
        small: [portrait: "text-sm-ptr ", landscape: "text-sm-lnd "],
	large: [portrait: "text-lrg-ptr ", landscape: "text-lrg-lnd "]];
      desc: String.SubStringDescriptor;
      pos: APosition ← lbh.pos;
      delta: ADistance = ADistanceForDots[
	IF lbh.font = small THEN smallFontAscent ELSE largeFontAscent, 1];
      IF lbh.mode = landscape THEN pos.x ← pos.x + delta 
      ELSE pos.y ← pos.y + delta;
      Another[];
      SubStringForLabel[@desc, lb];
      String.AppendSubString[labelString, @desc];
      OutC['(]; OutS[labelString]; OutS[") "];
      OutD[pos.x]; OutC[' ]; OutD[pos.y]; OutC[' ];
      OutS[stringCommand[lbh.font][lbh.mode]];
      RETURN [FALSE];
      END;
    minX: ADistance ← LAST[ADistance];
    maxY: ADistance ← FIRST[ADistance];
    FindMinMax: LineScan =
      BEGIN
      ChopUpLine[l, @box, NoteSegment];
      RETURN [FALSE];
      END;
    NoteSegment: PROC[
        pos1, pos2: APosition, 
        class: LineClass, 
        color: LineColor, 
        lWidth: LineWidth, 
        lengthen: [0..4], 
        box: POINTER TO ABox] =
      BEGIN
      minX ← MIN[minX, pos1.x, pos2.x];
      maxY ← MAX[maxY, pos1.y, pos2.y];
      END;
    JamLine: LineScan =
      BEGIN
      IF lth.width # clw THEN {OutC['0 + lth.width]; OutS[" line-width "]};
      clw ← lth.width;
      ChopUpLine[l, @box, JamLineSegment];
      RETURN [FALSE];
      END;
    JamLineSegment: PROC[
        pos1, pos2: APosition, 
        class: LineClass, 
        color: LineColor, 
        lWidth: LineWidth, 
        lengthen: [0..4], 
        box: POINTER TO ABox] =
      BEGIN
      IF color = white THEN RETURN;
      Another[];
      OutD[pos1.x - minX]; OutC[' ];
      OutD[maxY - pos1.y]; OutC[' ];
      OutD[pos2.x - minX]; OutC[' ];
      OutD[maxY - pos2.y];
      OutS[" draw-line "]; OutC[IODefs.CR];
      END;
    js ← NewByteStream[file, Write+Append];
    OutC['(]; OutS[file]; OutS[") =
(architect-scale) "]; OutF[state.sixteenthsPerFoot]; OutS[" .def

(scale) {architect-scale .mul 72 .mul 12 .div}.cvx .def
(scale2) {scale .exch scale .exch}.cvx .def
(line-width) {.setstrokewidth}.cvx .def
(text-sm-ptr) {{scale2 .translate 0 0 .setxy --set font-- .show}.cvx .dosave}.cvx .def
(text-sm-lnd) {{scale2 .translate 90 rotate 0 0 .setxy --set font-- .show}.cvx .dosave}.cvx .def
(text-lrg-ptr) {{scale2 .translate 0 0 .setxy --set font-- .show}.cvx .dosave}.cvx .def
(text-lrg-lnd) {{scale2 .translate 90 rotate 0 0 .setxy --set font-- .show}.cvx .dosave}.cvx .def
(draw-line) {scale2 .moveto scale2 .lineto .maskstroke} .cvx .def
(draw-picture-1) {
"];
    [] ← LinesInABox[@box, FindMinMax];
    [] ← LinesInABox[@box, JamLine];
    [] ← AllLabels[JamLabel];
    OutS["}.cvx .def

(draw-picture) {{"];
    FOR i: CARDINAL IN [1..cmdNum] DO
      OutS[" draw-picture-"]; OutN[i];
      ENDLOOP;
    OutS["}.cvx .dosave}.cvx .def
"];
    js.destroy[js];
    END;

  PressPicture: PUBLIC PROC [file: STRING] =
    BEGIN
    PressPictureInABox[
      file, [x1: 0, x2: LAST[ADistance], y1: 0, y2: LAST[ADistance]]];
    END;
    

  PressPictureInABox: PUBLIC PROC [file: STRING, box: ABox] =
    BEGIN OPEN PressDefs;
    scaleFactorDen: LONG INTEGER ← 16*12*scaleDen;
    scaleFactorNum: LONG INTEGER = LONG[2540]*state.sixteenthsPerFoot;
    currentFontSize: FontSize ← large;
    currentMode: LabelMode ← portrait;
    SetTheFont: PROC [font: FontSize, mode: LabelMode] =
      BEGIN
      IF font # currentFontSize OR mode # currentMode THEN
      SetFont[
	p: pfd,
	Name: "Helvetica"L,
	PointSize: IF font = small THEN 8 ELSE 14,
        Rotation: IF mode = landscape THEN 5400 ELSE 0];
      currentFontSize ← font; currentMode ← mode;
      END;
    Micas: PROC [dist: ADistance] RETURNS [Mica] =
      BEGIN
      longM: LONG INTEGER ← ALEOps.MulDiv[dist, scaleFactorNum, scaleFactorDen];
      RETURN[Short[longM]];
      END;
    XMicas: PROC [dist: ADistance] RETURNS [Mica] =
      BEGIN
      longM: LONG INTEGER ←
	 ALEOps.MulDiv[(dist-box.x1), scaleFactorNum, scaleFactorDen];
      RETURN[Short[longM + marginX]];
      END;
    YMicas: PROC [dist: ADistance] RETURNS [Mica] =
      BEGIN
      RETURN[PageTop - Micas[dist-box.y1] + marginY];
      END;
    LineMicaWidth: PROC [w: [0..4]] RETURNS [Mica] =
      BEGIN
      RETURN [(singleWidth*w)/state.blowup];
      END;
    PressLabel: LabelScan =
      BEGIN
      x,y: Mica;
      labelString: STRING ← [100];
      desc: String.SubStringDescriptor;
      pos: APosition ← lbh.pos;
      delta: ADistance = ADistanceForDots[
	IF lbh.font = small THEN smallFontAscent ELSE largeFontAscent, 1];
      IF pos.x ~IN [box.x1..box.x2] OR pos.y ~IN [box.y1..box.y2] THEN
	RETURN[FALSE];
      IF lbh.mode = landscape THEN pos.x ← pos.x + delta 
      ELSE pos.y ← pos.y + delta;
      x ← XMicas[pos.x];
      y ← YMicas[pos.y];
      SubStringForLabel[@desc, lb];
      String.AppendSubString[labelString, @desc];
      SetTheFont[lbh.font,lbh.mode];
      PutText[
        p: pfd,
	str: labelString,
	xleft: x,
	ybase: y];
      RETURN[FALSE];
      END;

    PressLine: LineScan =
      BEGIN
      ChopUpLine[l, @box, DrawLineSegment];
      RETURN[FALSE];
      END;

    DrawLineSegment: PROC[
        pos1, pos2: APosition, 
        class: LineClass, 
        color: LineColor, 
        lWidth: LineWidth, 
        lengthen: [0..4], 
        box: POINTER TO ABox] =
      BEGIN
      w, h: Mica;
      IF color = white THEN RETURN;
      SELECT class FROM
	horiz =>
	  BEGIN
	  x1: ADistance = MAX[pos1.x, box.x1];
	  x2: ADistance = MIN[pos2.x, box.x2];
       IF pos1.y ~IN [box.y1..box.y2] THEN RETURN;
	  h ← LineMicaWidth[lWidth];
	  w ← Micas[x2 - x1] + LineMicaWidth[lengthen];
	  PutRectangle[
	    p: pfd, 
	    xstart: XMicas[x1], 
	    ystart: YMicas[pos1.y] - h, 
	    xlen: w, ylen: h];
	  END;
	vert =>
	  BEGIN
	  y1: ADistance = MAX[pos1.y, box.y1];
	  y2: ADistance = MIN[pos2.y, box.y2];
       IF pos1.x ~IN [box.x1..box.x2] THEN RETURN;
	  w ← LineMicaWidth[lWidth];
	  h ← Micas[y2 - y1];
	  PutRectangle[
	    p: pfd, 
	    xstart: XMicas[pos1.x], 
	    ystart: YMicas[y1] - h, 
	    xlen: w, 
	    ylen: h];
	  END;
	ENDCASE =>
	  BEGIN
	  x1: ADistance = MAX[pos1.x, box.x1];
	  x2: ADistance = MIN[pos2.x, box.x2];
	  y1, y2: ADistance;
	  startX, startY, endX, endY: Mica;
	  dx, dy: Mica;
	  t: Mica = LineMicaWidth[lWidth];
	  a, b: Mica;
	  ady: CARDINAL;
	  l: LONG INTEGER;

          y1 ← pos1.y + ALEOps.MulDiv[(x1-pos1.x), (pos2.y-pos1.y), (pos2.x-pos1.x)];
          y2 ← pos1.y + ALEOps.MulDiv[(x2-pos1.x), (pos2.y-pos1.y), (pos2.x-pos1.x)];
--	  IF line is outside box THEN RETURN;
       IF y2 < box.y1 OR y1 > box.y2 THEN RETURN;
	  startX ← XMicas[x1]; startY ← YMicas[y1];
	  endX ← XMicas[x2]; endY ← YMicas[y2];
	  dx ← endX-startX;
	  dy ← endY-startY;
	  ady ← ABS[dy];
	  l ← Sqrt[
	      Inline.LongMult[dx, dx]+Inline.LongMult[ady, ady]];
	  a ← Short[ALEOps.MulDiv[LONG[dy], LONG[t], l]];
	  b ← Short[ALEOps.MulDiv[LONG[dx], LONG[t], l]];
	  StartOutline[p: pfd, x0: startX, y0: startY];
	  PutDrawTo[p: pfd, xend: startX+a, yend: startY-b];
	  PutDrawTo[p: pfd, xend: endX + a, yend: endY - b];
	  PutDrawTo[p: pfd, xend: endX, yend: endY];
	  PutDrawTo[p: pfd, xend: startX, yend: startY];
	  EndOutline[pfd];
	  END;
      RETURN;
      END;
    pfd: POINTER TO PressFileDescriptor =
      Storage.Node[ SIZE[PressFileDescriptor]];

    InitPressFileDescriptor[pfd, file];
    SetTheFont[small, portrait]; -- to make it font 0
    [] ← LinesInABox[@box, PressLine];
    [] ← AllLabels[PressLabel];
    WritePage[pfd];
    ClosePressFile[pfd];
    ClearText[];
    END;

  END.