-- ALEOut.mesa 
--    Edited by Sweet, September 5, 1980  5:19 PM

DIRECTORY
  ALEFormat,
  ALEOps,
  AltoDefs,
  Ascii,
  StreamDefs,
  Table;

ALEOut: PROGRAM IMPORTS ALEOps, StreamDefs, Table 
  EXPORTS ALEOps =
  BEGIN OPEN ALEOps;

-- tables defining the current symbol table

  ptb, ltb: Table.Base; -- used for writing out the file
  htb: Table.Base;
  ssb: STRING;
  lbb: Table.Base;

  UpdateBases: Table.Notifier = 
    BEGIN
    htb ← base[htType];
    ssb ← LOOPHOLE[base[ssType], STRING];
    lbb ← base[lbType];
    ptb ← base[ptType];
    ltb ← base[ltType];
    END;

  EveryPoint: PUBLIC PROC [action: PointScan] =
    BEGIN
    p: PTIndex;
    limit: CARDINAL = Table.Bounds[ptType].size;
    FOR p ← FIRST[PTIndex], p + SIZE[Point] WHILE 
	LOOPHOLE[p, CARDINAL] < limit DO
      [] ← action[p, @ptb[p]];
      ENDLOOP;
    END;

  WritePicture: PUBLIC PROC [file: STRING] =
    BEGIN OPEN StreamDefs;
    sth: DiskHandle;
    outHeader: ALEFormat.Header ← [];
    CountPoints: PointScan =
      BEGIN
      outHeader.points.length ← 
	outHeader.points.length + SIZE[ALEFormat.Point];
      RETURN[FALSE];
      END;
    CountLines: LineScan =
      BEGIN
      outHeader.lines.length ← 
	outHeader.lines.length + SIZE[ALEFormat.Line];
      RETURN[FALSE];
      END;
    CountLabels: LabelScan =
      BEGIN
      outHeader.labels.length ← 
	outHeader.labels.length + SIZE[ALEFormat.Label];
      RETURN[FALSE];
      END;
    WritePoint: PointScan =
      BEGIN
      op: ALEFormat.Point ← [pos: pth.pos];
      [] ← WriteBlock[sth, @op, SIZE[ALEFormat.Point]];
      RETURN[FALSE];
      END;
    WriteLine: LineScan =
      BEGIN
      p1: ALEFormat.PointIndex = LOOPHOLE [
	(LOOPHOLE[lth.p1, CARDINAL]/SIZE[ALEOps.Point]) *
	SIZE[ALEFormat.Point]];
      p2: ALEFormat.PointIndex = LOOPHOLE [
	(LOOPHOLE[lth.p2, CARDINAL]/SIZE[ALEOps.Point]) *
	SIZE[ALEFormat.Point]];
      ol: ALEFormat.Line ←
	[width: lth.width, texture: lth.texture, p1: p1, p2: p2];
      [] ← WriteBlock[sth, @ol, SIZE[ALEFormat.Line]];
      RETURN[FALSE];
      END;
    WriteLabel: LabelScan =
      BEGIN
      olb: ALEFormat.Label ← [font: lbh.font, hti: lbh.hti, pos: lbh.pos, mode: lbh.mode];
      [] ← WriteBlock[sth, @olb, SIZE[ALEFormat.Label]];
      RETURN[FALSE];
      END;
      
    Table.AddNotify[UpdateBases];
    outHeader.hash.length ← Table.Bounds[htType].size;
    outHeader.string.length ← Table.Bounds[ssType].size;
    EveryPoint[CountPoints];
    [] ← AllLines[CountLines];
    [] ← AllLabels[CountLabels];
    outHeader.hash.offset ← LOOPHOLE[SIZE[ALEFormat.Header]];
    outHeader.string.offset ← outHeader.hash.offset + outHeader.hash.length;
    outHeader.points.offset ←
      outHeader.string.offset + outHeader.string.length;
    outHeader.lines.offset ←
      outHeader.points.offset + outHeader.points.length;
    outHeader.labels.offset ← outHeader.lines.offset + outHeader.lines.length;
    sth ← NewWordStream[file, Write+Append];
    [] ← WriteBlock[sth, @outHeader, SIZE[ALEFormat.Header]];
    [] ← WriteBlock[sth, htb, outHeader.hash.length];
    [] ← WriteBlock[sth, ssb, outHeader.string.length];
    EveryPoint[WritePoint];
    [] ← AllLines[WriteLine];
    [] ← AllLabels[WriteLabel];
    pictureChanged ← FALSE;
    Table.DropNotify[UpdateBases];
    sth.destroy[sth];
    END;

  END.