-- ALEMerge.mesa -- Edited by Sweet, August 19, 1980 1:08 PM DIRECTORY ALEOps, AltoDefs, SegmentDefs, String, Table; ALEMerge: PROGRAM IMPORTS ALEOps, SegmentDefs EXPORTS ALEOps = BEGIN OPEN ALEOps; ptb, ltb, lbb: Table.Base; htb: Table.Base; ssb: STRING; ht: DESCRIPTOR FOR ARRAY HTIndex OF HTRecord; HVLength: PRIVATE CARDINAL = 71; HVIndex: TYPE = CARDINAL [0..HVLength); HTRecord: TYPE = RECORD [ anyInternal, anyPublic: BOOLEAN, link: HTIndex, ssIndex: CARDINAL]; HTIndex: TYPE = CARDINAL [0..Table.Limit/2); HTNull: HTIndex = FIRST[HTIndex]; -- points, lines, etc. Label: TYPE = RECORD [ free: BOOLEAN ← FALSE, selected: BOOLEAN ← TRUE, font: FontSize ← small, hti: HTIndex, pos: APosition]; LBIndex: TYPE = Table.Base RELATIVE POINTER [0..Table.Limit) TO Label; LBHandle: TYPE = POINTER TO Label; LBNull: LBIndex = LAST[LBIndex]; ALEHeader: TYPE = RECORD [ htTableSize: CARDINAL, ssTableSize: CARDINAL, pointTableSize: CARDINAL, lineTableSize: CARDINAL, labelTableSize: CARDINAL, freePoint: PTIndex, freeLine: LTIndex, freeLabel: LBIndex]; Point: TYPE = RECORD [ free, selected: BOOLEAN ← FALSE, lines: LTIndex ← LTNull, pos: APosition]; PTIndex: TYPE = Table.Base RELATIVE POINTER [0..Table.Limit) TO Point; PTHandle: TYPE = POINTER TO Point; PTNull: PTIndex = LAST[PTIndex]; Line: TYPE = RECORD [ free: BOOLEAN ← FALSE, selected: BOOLEAN ← TRUE, p1: PTIndex, width: LineWidth, p2: PTIndex, repainted: BOOLEAN ← FALSE, texture: LineTexture, p1Chain: LTIndex, class: LineClass, p2Chain: LTIndex]; LTIndex: TYPE = Table.Base RELATIVE POINTER [0..Table.Limit) TO Line; LTHandle: TYPE = POINTER TO Line; LTNull: LTIndex = LAST[LTIndex]; PointScan: TYPE = PROCEDURE [p: PTIndex, pth: PTHandle] RETURNS [stop: BOOLEAN]; LineScan: TYPE = PROCEDURE [l: LTIndex, lth: LTHandle] RETURNS [stop: BOOLEAN]; LabelScan: TYPE = PROCEDURE [lb: LBIndex, lbh: LBHandle] RETURNS [stop: BOOLEAN]; AllMyLines: PROC [action: LineScan] RETURNS [l: LTIndex] = BEGIN FOR l ← FIRST[LTIndex], l + SIZE[Line] WHILE LOOPHOLE[l, CARDINAL] < header.lineTableSize DO IF ~ltb[l].free AND action[l, @ltb[l]] THEN RETURN; ENDLOOP; RETURN[LTNull] END; AllMyLabels: PROC [action: LabelScan] RETURNS [lb: LBIndex] = BEGIN FOR lb ← FIRST[LBIndex], lb + SIZE[Label] WHILE LOOPHOLE[lb, CARDINAL] < header.labelTableSize DO IF ~lbb[lb].free AND action[lb, @lbb[lb]] THEN RETURN; ENDLOOP; RETURN[LBNull] END; header: POINTER TO ALEHeader; MergeInFile: PUBLIC PROC [file: STRING] = BEGIN OPEN SegmentDefs; fh: FileHandle = NewFile[file, Read! FileNameError => GO TO cant]; seg: FileSegmentHandle = NewFileSegment[fh, DefaultBase, DefaultPages, Read]; AddThisLine: LineScan = BEGIN pos1: APosition = ptb[lth.p1].pos; pos2: APosition = ptb[lth.p2].pos; currentWidth ← lth.width; currentTexture ← lth.texture; DrawLine[pos1, pos2, FALSE]; RETURN[FALSE]; END; AddThisLabel: LabelScan = BEGIN desc: String.SubStringDescriptor; pos: APosition = lbh.pos; currentFont ← lbh.font; SubStringForHash[@desc, lbh.hti]; SSDrawLabel[@desc, pos]; RETURN[FALSE]; END; SwapIn[seg]; header ← FileSegmentAddress[seg]; htb ← LOOPHOLE[header + SIZE[ALEHeader] + LAST[HVIndex] + 1]; ht ← DESCRIPTOR[htb, header.htTableSize/SIZE[HTRecord]]; ssb ← LOOPHOLE[htb + header.htTableSize + 1]; ptb ← LOOPHOLE[ssb + header.ssTableSize]; ltb ← LOOPHOLE[ptb + header.pointTableSize]; lbb ← LOOPHOLE[ltb + header.lineTableSize]; [] ← AllMyLines[AddThisLine]; [] ← AllMyLabels[AddThisLabel]; Unlock[seg]; DeleteFileSegment[seg]; ClearText[]; EXITS cant => OutString[" not found"L]; END; SubString: TYPE = String.SubString; CharsPerWord: PRIVATE CARDINAL = AltoDefs.CharsPerWord; SubStringForHash: PROC [s: SubString, hti: HTIndex] = { s.base ← ssb; IF hti = HTNull THEN s.offset ← s.length ← 0 ELSE s.length ← ht[hti].ssIndex - (s.offset ← ht[hti-1].ssIndex)}; END.