<> <> <> <> DIRECTORY Atom, TSTypes, TSObject, TSOps, TSDumper, TSFont, TSGlue, TSOutput, NodeStyle, NodeStyleExtra, TSAList, JaMBasic, JaMOps, Rope, TSJaMPageBuilder ; TSJaMPageBuilderImpl: PROGRAM IMPORTS Atom, TSTypes, TSObject, TSOps, TSDumper, TSFont, TSOutput, NodeStyle, NodeStyleExtra, TSAList, JaMOps, Rope EXPORTS TSJaMPageBuilder = BEGIN OPEN TSTypes; ROPE: TYPE = Rope.ROPE; Frame: TYPE = NodeStyleExtra.Frame; Handle: TYPE = REF TPStateRec; TPStateRec: TYPE = RECORD [ pageReader: TSObject.ListReader, currentMarks: TSObject.MarkList, topMargin, leftMargin, pageHeight, paperHeight, paperWidth: Dimn, columns: NAT, output: TSOutput.Handle, curFont: TSFont.Ref, styleName: NodeStyle.Name, documentName: ROPE, abortCheckProc: TSJaMPageBuilder.AbortCheckProc, stack: LIST OF REF ANY _ NIL, aborted: BOOLEAN _ FALSE ]; RunPageBuilder: PUBLIC PROCEDURE [ galley: TSObject.ItemList, style: NodeStyle.Ref, output: TSOutput.Handle, abortCheckProc: TSJaMPageBuilder.AbortCheckProc _ NIL, documentName: Rope.ROPE _ NIL -- only a hint ] RETURNS [aborted: BOOLEAN] = { frame: Frame _ NodeStyleExtra.GetFrame[style: style, styleName: style.GetStyleName[], kind: print]; handle: Handle _ NEW[TPStateRec]; handle.styleName _ style.GetStyleName[]; RegisterJaMProcs[frame]; handle.paperHeight _ Pt[style.GetPageLength[]]; handle.paperWidth _ Pt[style.GetPageWidth[]]; handle.pageHeight _ Pt[style.GetPageLength[]-style.GetTopMargin[]-style.GetHeaderMargin[]-style.GetFooterMargin[]-style.GetBottomMargin[]]; handle.topMargin _ Pt[style.GetTopMargin[]]; handle.leftMargin _ Pt[style.GetLeftMargin[]]; handle.columns _ style.GetColumns[]; handle.documentName _ documentName; handle.abortCheckProc _ abortCheckProc; handle.pageReader _ TSOps.BreakUp[ list: TSOps.InsertLeading[galley], direction: down, size: handle.pageHeight ].CreateReader[]; handle.output _ output; TSAList.Define[LOOPHOLE[frame], handle]; JaMOps.Execute[frame, NodeStyleExtra.CVX[ NodeStyleExtra.NameToObject[pageBuilderName] ]]; TSAList.UnDefine[LOOPHOLE[frame]]; NodeStyleExtra.FreeFrame[frame: frame, name: handle.styleName, kind: print]; aborted _ handle.aborted; }; GoodByeScript: PROCEDURE [f: Frame] = { handle: Handle _ NARROW[TSAList.Find[LOOPHOLE[f]], Handle]; IF handle = NIL THEN { NodeStyleExtra.FreeFrame[frame: f, name: handle.styleName, kind: print]; }; }; pageBuilderName: NodeStyle.Name = NodeStyleExtra.MakeName["PageBuilder"]; PushItem: PROCEDURE [handle: Handle, item: REF ANY] = BEGIN handle.stack _ CONS[item, handle.stack]; END; PopItem: PROCEDURE [handle: Handle] RETURNS [item: REF ANY] = BEGIN IF handle.stack = NIL THEN item _ NIL ELSE { t: LIST OF REF ANY _ handle.stack; handle.stack _ t.rest; item _ t.first; t.first _ NIL; t.rest _ NIL; } END; PopList: PROCEDURE [handle: Handle, count: NAT] RETURNS [itemList: TSObject.ItemList] = BEGIN list: LIST OF REF ANY _ NIL; THROUGH [0..count) DO item: REF ANY _ PopItem[handle]; IF item # NIL THEN list _ CONS[item, list]; ENDLOOP; itemList _ TSObject.ItemListFromExplicitList[list]; END; PopRope: PROCEDURE [f: Frame] RETURNS [rope: ROPE] = BEGIN s: string JaMBasic.Object _ JaMOps.PopString[f.opstk]; C: PROC[c: CHAR] RETURNS [BOOLEAN] = {t[t.length]_c; t.length _ t.length+1; RETURN[FALSE]}; t: REF TEXT _ NEW[TEXT[s.length]]; t.length _ 0; JaMOps.StringForAll[s, C]; rope _ Rope.FromRefText[t]; END; PushRope: PROCEDURE [f: Frame, rope: ROPE] = BEGIN JaMOps.Push[ f.opstk, JaMOps.MakeString[LOOPHOLE[rope.ToRefText[], LONG STRING]] ]; END; Page: SAFE PROCEDURE [f: Frame] = TRUSTED BEGIN -- Pushes the next page box onto the stack handle: Handle _ NARROW[TSAList.Find[LOOPHOLE[f]], Handle]; IF handle.abortCheckProc # NIL THEN handle.aborted _ handle.abortCheckProc[]; DO -- until we find a page box or empty the page list IF handle.aborted OR handle.pageReader = NIL OR handle.pageReader.End[] THEN { JaMOps.PushBoolean[f.opstk, FALSE]; IF handle.pageReader # NIL THEN handle.pageReader.DestroyReader[]; handle.pageReader _ NIL; EXIT } ELSE { IF ISTYPE[handle.pageReader.CurrentItem[], TSObject.MarkList] THEN { thisPageMarks: TSObject.MarkList _ NARROW[handle.pageReader.CurrentItem[], TSObject.MarkList]; handle.currentMarks _ MergeMarkLists[thisPageMarks, handle.currentMarks]; handle.pageReader.Next[]; LOOP; }; PushItem[handle, handle.pageReader.CurrentItem[]]; handle.pageReader.Next[]; JaMOps.PushBoolean[f.opstk, TRUE]; EXIT }; ENDLOOP; END; ShipOut: SAFE PROCEDURE [f: Frame] = TRUSTED BEGIN -- Sends a constructed page to the outside world handle: Handle _ NARROW[TSAList.Find[LOOPHOLE[f]], Handle]; item: REF ANY _ PopItem[handle]; handle.output.newPageProc[handle.output]; IF item # NIL AND ISTYPE[item, TSObject.Box] THEN { IF handle.output.pageSizeProc # NIL THEN handle.output.pageSizeProc[ handle.output, handle.paperHeight, handle.paperWidth ]; handle.output.BoxOut[ xRef: handle.leftMargin, yRef: SubDimn[handle.paperHeight, handle.topMargin], box: NARROW[item, TSObject.Box]^ ]; }; END; BoxFromHList: PROCEDURE [list: TSObject.ItemList] RETURNS [box: TSObject.Box] = { source: TSObject.ListReader _ list.CreateReader[]; box _ TSOps.Package[source: source, direction: right, desired: [zeroDimn,nilDimn,nilDimn,nilDimn]].box; source.DestroyReader[]; }; Columns: SAFE PROCEDURE [f: Frame] = TRUSTED BEGIN handle: Handle _ NARROW[TSAList.Find[LOOPHOLE[f]], Handle]; JaMOps.PushInteger[f.opstk, handle.columns]; END; DocumentName: SAFE PROCEDURE [f: Frame] = TRUSTED BEGIN handle: Handle _ NARROW[TSAList.Find[LOOPHOLE[f]], Handle]; PushRope[f, handle.documentName]; END; TextBox: SAFE PROCEDURE [f: Frame] = TRUSTED BEGIN handle: Handle _ NARROW[TSAList.Find[LOOPHOLE[f]], Handle]; rope: ROPE _ PopRope[f]; IF handle.curFont = NIL THEN handle.curFont _ TSFont.Lookup["Helvetica"]; PushItem[handle, BoxFromHList[TSOps.ItemListFromRope[handle.curFont, rope]]]; END; TextFont: SAFE PROCEDURE [f: Frame] = TRUSTED BEGIN handle: Handle _ NARROW[TSAList.Find[LOOPHOLE[f]], Handle]; fontSize: Dimn _ RealDimn[JaMOps.PopReal[f.opstk], pt]; fontName: ROPE _ PopRope[f]; handle.curFont _ TSFont.Lookup[fontName, fontSize]; END; Vbox: SAFE PROCEDURE [f: Frame] = TRUSTED BEGIN handle: Handle _ NARROW[TSAList.Find[LOOPHOLE[f]], Handle]; source: TSObject.ListReader _ PopList[handle, JaMOps.PopCardinal[f.opstk]].CreateReader[]; box: TSObject.Box _ TSOps.Package[ source: source, direction: down, desired: [nilDimn, nilDimn, zeroDimn, nilDimn] ].box; PushItem[handle, box]; source.DestroyReader[]; END; Hbox: SAFE PROCEDURE [f: Frame] = TRUSTED BEGIN handle: Handle _ NARROW[TSAList.Find[LOOPHOLE[f]], Handle]; PushItem[handle, BoxFromHList[ PopList[handle, JaMOps.PopCardinal[f.opstk]] ]]; END; VboxTo: SAFE PROCEDURE [f: Frame] = TRUSTED BEGIN handle: Handle _ NARROW[TSAList.Find[LOOPHOLE[f]], Handle]; size: Dimn _ RealDimn[JaMOps.PopReal[f.opstk], pt]; source: TSObject.ListReader _ PopList[handle, JaMOps.PopCardinal[f.opstk]].CreateReader[]; PushItem[handle, TSOps.Package[ source: source, direction: down, desired: [nilDimn, nilDimn, zeroDimn, size] ].box]; source.DestroyReader[]; END; HboxTo: SAFE PROCEDURE [f: Frame] = TRUSTED BEGIN handle: Handle _ NARROW[TSAList.Find[LOOPHOLE[f]], Handle]; size: Dimn _ RealDimn[JaMOps.PopReal[f.opstk], pt]; source: TSObject.ListReader _ PopList[handle, JaMOps.PopCardinal[f.opstk]].CreateReader[]; PushItem[handle, TSOps.Package[ source: source, direction: right, desired: [zeroDimn, size, nilDimn, nilDimn] ].box]; source.DestroyReader[]; END; fillGlue: TSObject.Glue = TSObject.pZone.NEW[TSGlue.Glue _ [zeroDimn, TSGlue.fill, zeroDimn]]; Fill: SAFE PROCEDURE [f: Frame] = TRUSTED BEGIN handle: Handle _ NARROW[TSAList.Find[LOOPHOLE[f]], Handle]; PushItem[handle, fillGlue]; END; <> DumpBox: SAFE PROCEDURE [f: Frame] = TRUSTED BEGIN handle: Handle _ NARROW[TSAList.Find[LOOPHOLE[f]], Handle]; TSDumper.DumpList[TSObject.SingletonList[PopItem[handle]]]; END; emptyBox: TSObject.Box = NEW[TSObject.BoxRec _ [[zeroDimn, zeroDimn, zeroDimn, zeroDimn], empty[]]]; GetMark: SAFE PROCEDURE [f: Frame] = TRUSTED { handle: Handle _ NARROW[TSAList.Find[LOOPHOLE[f]], Handle]; markKind: ROPE _ PopRope[f]; IF handle.currentMarks # NIL THEN { markAtom: ATOM _ Atom.MakeAtom[markKind]; l: REF TSObject.MarkListItem _ handle.currentMarks; UNTIL l = NIL OR l.markKind = markAtom DO l _ l.link; ENDLOOP; IF l = NIL THEN PushItem[handle, emptyBox] ELSE PushItem[handle, l.markValue]; } ELSE PushItem[handle, emptyBox]; }; GetFirstMark: SAFE PROCEDURE [f: Frame] = TRUSTED { handle: Handle _ NARROW[TSAList.Find[LOOPHOLE[f]], Handle]; markKind: ROPE _ PopRope[f]; IF handle.currentMarks # NIL THEN { markAtom: ATOM _ Atom.MakeAtom[markKind]; l: REF TSObject.MarkListItem _ handle.currentMarks; last: REF TSObject.MarkListItem _ NIL; UNTIL l = NIL DO IF l.markKind = markAtom THEN last _ l; l _ l.link; ENDLOOP; IF last = NIL THEN PushItem[handle, emptyBox] ELSE PushItem[handle, last.markValue]; } ELSE PushItem[handle, emptyBox]; }; MergeMarkLists: PROCEDURE [new, old: TSObject.MarkList] RETURNS [TSObject.MarkList] = { <> p, q, r: TSObject.MarkList; <> p _ old; UNTIL p = NIL DO r _ p; q _ p.link; UNTIL q = NIL DO IF p.markKind = q.markKind THEN r.link _ q.link ELSE r _ q; q _ q.link; ENDLOOP; p _ p.link; ENDLOOP; <> p _ new; UNTIL p = NIL OR p.link = NIL DO p _ p.link; ENDLOOP; IF p = NIL THEN new _ old ELSE p.link _ old; RETURN [new]; }; ExchBox: SAFE PROCEDURE [f: Frame] = TRUSTED { handle: Handle _ NARROW[TSAList.Find[LOOPHOLE[f]], Handle]; item1: REF ANY _ PopItem[handle]; item2: REF ANY _ PopItem[handle]; PushItem[handle, item1]; PushItem[handle, item2]; }; RegisterJaMProcs: PROCEDURE [f: Frame] = BEGIN OPEN NodeStyleExtra; []_StyleCommand[f, ".page", Page]; -- -> .true . OR -> .false []_StyleCommand[f, ".getmark", GetMark]; -- -> (markkind) -> []_StyleCommand[f, ".getfirstmark", GetFirstMark]; -- -> (markkind) -> []_StyleCommand[f, ".columns", Columns]; -- -> .true . OR -> .false []_StyleCommand[f, ".shipout", ShipOut]; -- -> . The box is sent out []_StyleCommand[f, ".documentname", DocumentName]; -- -> string . []_StyleCommand[f, ".textbox", TextBox]; -- string -> . uses current font []_StyleCommand[f, ".textfont", TextFont]; -- fontnamestring fontpointsize -> . sets current font []_StyleCommand[f, ".vbox", Vbox]; -- ... n -> . []_StyleCommand[f, ".hbox", Hbox]; -- ... n -> . []_StyleCommand[f, ".vboxto", VboxTo]; -- ... n height -> . []_StyleCommand[f, ".hboxto", HboxTo]; -- ... n height -> . []_StyleCommand[f, ".fill", Fill]; -- -> . []_StyleCommand[f, ".dumpbox", DumpBox]; -- -> . []_StyleCommand[f, ".exchbox", ExchBox]; -- -> END; END. Michael Plass, September 1, 1982 9:21 pm: Put in calls to TSObject.DestroyReader. Michael Plass, November 2, 1982 2:39 pm. Tioga formatted. Michael Plass, November 12, 1982 10:11 am. pZone. Michael Plass, November 16, 1982 2:36 pm. Changed to use some of the page layout parameters. Michael Plass, November 17, 1982 9:34 am. Fixed frame and style stuff. Michael Plass, November 17, 1982 11:13 am. Fixed bug that prevented .page from working after the end marker was sent. Michael Plass, February 15, 1983 1:04 pm. Removed dependency on JaMTypeScript. Rick Beach, May 17, 1983 10:17 am. Added .getmark routines., Rick <> <> <> <> <<>> <<>>