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 ΐTSJaMPageBuilderImpl.mesa Edited by: Maxwell, January 25, 1983 2:39 pm Michael Plass, February 15, 1983 1:03 pm Last Edited by: Beach, May 24, 1983 5:06 pm This proc can dump boxes, for use in debugging Merge the new and old lists of marks into one list with old duplicates eliminated, preserving order. Using a niave n**2 search, eliminate duplicates from the old list. Find the end of the new list to concatenate the old one. Edited on May 17, 1983 10:16 am, by Beach Added .exchbox to permit a layout style to get a page, then get headers which must precede the page. Edited on May 24, 1983 8:52 am, by Beach Added MergeMarkLists to properly maintain a page history of marks., MergeMarkLists Κ – "cedar" style˜Jšœ™J™,Jšœ)™)J™+šΟk ˜ J˜J˜J˜ J˜J˜ J˜J˜J˜ J˜ J˜J˜J˜ J˜J˜J˜J˜J˜—šœ˜Jš˜J˜lJšœ˜—Jšœœ ˜J˜Jšœœœ˜Jšœœ˜#J˜Jšœœœ ˜šœ œœ˜J˜ J˜ J˜AJšœ œ˜ J˜J˜J˜Jšœœ˜J˜0Jš œœœœœœ˜Jšœ œ˜J˜J˜—šΟnœœ œ˜"J˜J˜J˜Jšœ2œ˜6JšœœœΟc˜,J˜Jšœ œ˜Jšœc˜cJšœœ ˜!Jšœ(˜(J˜Jšœ/˜/Jšœ-˜-Jšœ‹˜‹Jšœ,˜,Jšœ.˜.Jšœ$˜$J˜#J˜'˜"J˜"J˜J˜J˜—J˜Jšœœ˜(šœ%œ˜)J˜,J˜—Jšœœ ˜"JšœL˜LJ˜J˜J˜—šž œ œ˜'Jšœœœ˜;šœ œœ˜JšœH˜HJ˜—J˜J˜—J˜IJ˜šžœ œœœ˜5Jš˜Jšœœ˜(Jšœ˜J˜—š žœ œœœœ˜=Jš˜Jšœœœ˜%šœ˜Jš œœœœœ˜"J˜J˜Jšœ œ˜Jšœ œ˜ J˜—Jšœ˜J˜—šžœ œœ˜/Jšœ ˜'Jš˜Jš œœœœœœ˜šœ ˜Jšœœœ˜ Jšœœœœ ˜+Jšœ˜—J˜3Jšœ˜J˜—šžœ œ œœ˜4Jš˜J˜6š œœœœœ˜$Jšœ'œœ˜6—Jš œœœœœ ˜"J˜ Jšœœ˜J˜Jšœ˜J˜—šžœ œœ˜,Jš˜˜ J˜Jšœœœœ˜:J˜—Jšœ˜J˜—šžœœ ˜!Jš œŸ*˜8Jšœœœ˜;Jšœœœ*˜MšœŸ2˜5šœœœœ˜NJšœœ˜#Jšœœ#˜BJšœœ˜Jš˜J˜—šœ˜šœœ5œ˜DJšœ#œ5˜^JšœI˜IJšœ˜Jšœ˜J˜—Jšœ2˜2J˜Jšœœ˜"Jš˜J˜—Jšœ˜—Jšœ˜J˜—šžœœ ˜$Jš œŸ0˜>Jšœœœ˜;Jšœœœ˜ J˜)š œœœœ˜3šœ˜(šœ˜Jšœ4˜4Jšœ˜——˜J˜J˜4Jšœœ˜ J˜—J˜—Jšœ˜J˜—šž œ œœ˜QJ˜2J˜gJ˜J˜J˜—šžœœ ˜$Jš ˜ Jšœœœ˜;Jšœ,˜,Jšœ˜J˜—šž œœ ˜)Jš ˜ Jšœœœ˜;J˜!Jšœ˜J˜—šžœœ ˜$Jš ˜ Jšœœœ˜;Jšœœ˜Jšœœœ-˜IJ˜MJšœ˜J˜—šžœœ ˜%Jš ˜ Jšœœœ˜;J˜7Jšœ œ˜J˜3Jšœ˜J˜—šžœœ ˜!Jš ˜ Jšœœœ˜;J˜Z˜"J˜J˜J˜.J˜—J˜J˜Jšœ˜J˜—šžœœ ˜!Jš ˜ Jšœœœ˜;˜J˜,J˜—Jšœ˜J˜—šžœœ ˜#Jš ˜ Jšœœœ˜;J˜3J˜Z˜J˜J˜J˜,J˜—J˜Jšœ˜J˜—šžœœ ˜#Jš ˜ Jšœœœ˜;J˜3J˜Z˜J˜J˜J˜,J˜—J˜Jšœ˜J˜—Jšœ)œ2˜^J˜šžœœ ˜!Jš ˜ Jšœœœ˜;J˜Jšœ˜J˜—JšŸ.™.šžœœ ˜$Jš ˜ Jšœœœ˜;J˜;Jšœ˜J˜—JšœœH˜dšΟbœœœ˜.Jšœœœ˜;Jšœ œ˜šœœœ˜#Jšœ œ˜)J˜3šœœœ˜)J˜ Jš˜—Jšœœœ˜*Jšœ˜#J˜—Jšœ˜ J˜J˜—š  œœœ˜3Jšœœœ˜;Jšœ œ˜šœœœ˜#Jšœ œ˜)Jšœœ-˜3Jšœœœ˜&šœœ˜Jšœœ ˜'J˜ Jš˜—Jšœœœ˜-Jšœ"˜&J˜—Jšœ˜ J˜J˜—šžœ œœ˜WJ™dJšœ˜J™BJ˜šœœ˜J˜J˜ šœœ˜Jšœœœ˜;J˜ Jšœ˜—J˜ Jšœ˜—J™8J˜š œœœ œ˜ J˜ Jšœ˜—Jšœœœ œ˜,Jšœ˜ Jšœ˜J˜—šžœœœ˜.Jšœœœ˜;Jšœœœ˜!Jšœœœ˜!J˜J˜J˜J˜—šžœ œ ˜(Jšœœ˜Jšœ#Ÿ%˜HJšœ)Ÿ2˜[Jšœ3Ÿ2˜eJšœ)Ÿ%˜NJšœ)Ÿ!˜JJšœ3Ÿ˜BJšœ)Ÿ&˜OJšœ+Ÿ7˜bJšœ#Ÿ+˜NJšœ#Ÿ+˜NJšœ'Ÿ2˜YJšœ'Ÿ2˜YJšœ#Ÿ˜6Jšœ)Ÿ ˜6Jšœ)Ÿ!˜JJšœ˜J˜—Jšœ˜J˜J˜RJšœ9˜9Jšœ1˜1Jšœ\˜\JšœF˜FJšœu˜uJšœN˜NJšœ;Οr˜A™)Jšœ‘œV™d—™(Jšœ‘œ.‘™R—J™J™—…—,ΐ;œ