<> <<>> <> <> <> DIRECTORY BasicTime USING [GMT], Buttons USING [Button, ButtonProc, Create], Commander USING [CommandProc, Register], Containers USING [ChildXBound, ChildYBound, Container, Create], FS USING [ComponentPositions, ExpandName], Icons USING [IconFlavor, NewIconFromFile], Imager USING [Context, Create, NewPage, Reset, SpecialOp], ImagerBridge USING [SetViewFromGraphicsContext], ImagerPD USING [Hornet, PDFileDescription, PlateMaker], ImagerPDExtras, IO USING [Close, int, PutChar, PutF, PutFR, PutRope, rope, STREAM, time, refAny], IP USING [State], IPExtras USING [DoPage, OpenMaster, PageCount], IPUtils USING [ToEncoded, ToWritten], Loader USING [BCDBuildTime], Menus USING [AppendMenuEntry, CreateEntry, CreateMenu, Menu, MenuProc], Process USING [Pause, SecondsToTicks], Real, Rope USING [Concat, Find, ROPE, Substr], Rules USING [Create, Rule], ViewerClasses USING [PaintProc, Viewer, ViewerClass, ViewerClassRec], ViewerIO USING [CreateViewerStreams], ViewerOps USING [CreateViewer, PaintViewer, RegisterViewerClass], ViewerTools USING [MakeNewTextViewer, GetContents, SetContents, SetSelection], ViewRec USING [ViewRef]; IPToolImpl: CEDAR MONITOR LOCKS data USING data: Data IMPORTS Buttons, Commander, Containers, FS, Icons, Imager, ImagerBridge, ImagerPD, ImagerPDExtras, IO, IPExtras, IPUtils, Loader, Menus, Process, Real, Rope, Rules, ViewerIO, ViewerOps, ViewerTools, ViewRec = { -- Here is the layout of the tool -- --========================================================================-- -- Interpress -- --========================================================================-- -- Load Show Next PDOptions Print PrintAll Write Read -- --========================================================================-- -- Master: Test.Interpress -- -- Written: Test.IPWritten -- --========================================================================-- -- Interpress Tool of March 31, 1983 -- -- Test.Interpress -> WTest.Interpress -- -- -- -- -- -- -- -- -- --========================================================================-- -- Here is the layout of a page viewer -- --========================================================================-- -- Test.Interpress, page 3 -- --========================================================================-- -- -- -- -- -- . . . -- -- -- --========================================================================-- ROPE: TYPE = Rope.ROPE; STREAM: TYPE = IO.STREAM; Viewer: TYPE = ViewerClasses.Viewer; Button: TYPE = Buttons.Button; Data: TYPE = REF DataRep; DataRep: TYPE = MONITORED RECORD [ -- the data for a particular tool instance outer: Containers.Container _ NIL, -- handle for the enclosing container busy: BOOL _ FALSE, height: NAT _ 0, -- height measured from the top of the container logViewer: Viewer, -- contains error log log: STREAM, -- output stream for writing to error log masterButton: Button, -- Master: button masterField: Viewer, -- contains name of Master file writtenButton: Button, -- Written: button writtenField: Viewer, -- contains name of Written file pageButton: Button, -- Page: button pageField: Viewer, -- contains page number page: Viewer, -- viewer for showing a page masterName: ROPE, -- name of current master pageNumber: NAT, -- current page number state: IP.State, -- state of the Interpress interpreter display: Imager.Context, -- imager context for the display pdOptions: ImagerPD.PDFileDescription _ NIL ]; Lock: ENTRY PROC[data: Data] RETURNS[BOOL] = { IF data.busy THEN RETURN[FALSE] ELSE RETURN[data.busy _ TRUE]; }; Unlock: ENTRY PROC[data: Data] = { data.busy _ FALSE }; lineHeight: CARDINAL = 15; -- how tall to make each line of items lineLeading: CARDINAL = 2; -- vertical leading space between lines totalWidth: CARDINAL = 444; -- width of the entire viewer margin: CARDINAL = 8; -- left and right margins entryHSpace: CARDINAL = 10; -- horizontal space between items in a line MakeIPTool: Commander.CommandProc = { CreateTool[] }; CreateTool: PROC = { data: Data = NEW[DataRep]; menu: Menus.Menu = MakeMenu[data]; buildTime: BasicTime.GMT ~ Loader.BCDBuildTime[CreateTool]; data.outer _ Containers.Create[[-- construct the outer container' name: "Interpress Tool", -- name displayed in the caption menu: menu, iconic: FALSE, column: right, -- initially in the right column scrollable: FALSE ]]; <> MakeFilePart[data]; MakeRule[data, 1]; MakeLogPart[data, 100]; data.page _ CreatePage[data]; data.log.PutF["Interpress Tool of %g\n", IO.time[buildTime]]; ViewerOps.PaintViewer[data.outer, all]; -- reflect above change }; PageData: TYPE = REF PageDataRep; PageDataRep: TYPE = RECORD[w: NAT]; -- instance data for Interpress viewers CreatePage: PROC[data: Data] RETURNS[ViewerClasses.Viewer] = { viewer: ViewerClasses.Viewer = ViewerOps.CreateViewer[ flavor: $Page, info: [ name: "Interpress Page", data: data, iconic: FALSE, column: left, scrollable: FALSE ] ]; RETURN[viewer]; }; LongOperation: PROC[log: STREAM, n: NAT] = { THROUGH [0..n) DO log.PutChar['.]; Process.Pause[Process.SecondsToTicks[1]]; ENDLOOP; }; MakeMenu: PROC[data: Data] RETURNS[Menus.Menu] = { menu: Menus.Menu = Menus.CreateMenu[]; Menus.AppendMenuEntry[menu: menu, entry: Menus.CreateEntry[name: "Load", proc: LoadProc, clientData: data] ]; Menus.AppendMenuEntry[menu: menu, entry: Menus.CreateEntry[name: "Show", proc: ShowProc, clientData: data] ]; Menus.AppendMenuEntry[menu: menu, entry: Menus.CreateEntry[name: "Next", proc: NextProc, clientData: data] ]; Menus.AppendMenuEntry[menu: menu, entry: Menus.CreateEntry[name: "PDOptions", proc: PDOptionsProc, clientData: data] ]; Menus.AppendMenuEntry[menu: menu, entry: Menus.CreateEntry[name: "Print", proc: PrintProc, clientData: data] ]; Menus.AppendMenuEntry[menu: menu, entry: Menus.CreateEntry[name: "PrintAll", proc: PrintAllProc, clientData: data] ]; Menus.AppendMenuEntry[menu: menu, entry: Menus.CreateEntry[name: "Write", proc: WriteProc, clientData: data] ]; Menus.AppendMenuEntry[menu: menu, entry: Menus.CreateEntry[name: "Read", proc: ReadProc, clientData: data] ]; <> <> <> <<];>> RETURN[menu]; }; PaintPageViewer: PROC[data: Data] = { page: Viewer ~ data.page; page.name _ IO.PutFR["%g, page %g", IO.rope[data.masterName], IO.int[data.pageNumber]]; ViewerOps.PaintViewer[viewer: page, hint: all, whatChanged: $SetView]; <> IF page.iconic THEN RETURN; data.state.imager _ data.display; [] _ IPExtras.DoPage[data.state, data.pageNumber]; }; GetPDFileDescription: PROC[data: Data] RETURNS[ImagerPD.PDFileDescription] ~ { IF data.pdOptions = NIL THEN RETURN [ImagerPD.Hornet[PDName[data.masterName]]] ELSE RETURN [data.pdOptions]; }; PrintPage: PROC[data: Data] = { log: STREAM ~ data.log; self: IP.State ~ data.state; masterName: ROPE ~ data.masterName; page: NAT ~ data.pageNumber; pd: Imager.Context _ NIL; pdOptions: ImagerPD.PDFileDescription ~ GetPDFileDescription[data]; log.PutF["Writing page %g of %g to %g ...", IO.int[page], IO.rope[masterName], IO.rope[pdOptions.fileName]]; self.imager _ pd _ Imager.Create[$PD, pdOptions]; [] _ IPExtras.DoPage[self, page]; [] _ Imager.SpecialOp[pd, $Close, NIL]; log.PutRope["done.\n"]; }; PrintAll: PROC[data: Data] = { log: STREAM ~ data.log; self: IP.State ~ data.state; masterName: ROPE ~ data.masterName; count: NAT ~ IPExtras.PageCount[self]; pd: Imager.Context _ NIL; pdOptions: ImagerPD.PDFileDescription ~ GetPDFileDescription[data]; log.PutF["Writing %g to %g (%g pages) ...", IO.rope[masterName], IO.rope[pdOptions.fileName], IO.int[count]]; self.imager _ pd _ Imager.Create[$PD, pdOptions]; FOR page: NAT IN[1..count] DO log.PutF[" %g", IO.int[page]]; [] _ IPExtras.DoPage[self, page]; IF page Unlock[data]]; Unlock[data]; }; }; LoadProc: Buttons.ButtonProc = { Do[LoadMaster, NARROW[clientData]]; }; ShowProc: Menus.MenuProc = { Do[PaintPageViewer, NARROW[clientData]]; }; viewRecBuggy: BOOL _ TRUE; versatecExpansion: REAL _ 4.5; PDOptionsProc: Menus.MenuProc = { SetPDOptions: PROC[data: Data] ~ { fileName: ROPE ~ PDName[data.masterName]; new: ImagerPD.PDFileDescription ~ SELECT mouseButton FROM red => ImagerPD.Hornet[fileName], blue => ImagerPD.PlateMaker[fileName], yellow => ImagerPDExtras.ColorVersatec[fileName], ENDCASE => ImagerPD.Hornet[fileName]; IF mouseButton = blue THEN { new.sResolution _ new.fResolution _ 1200; new.imageSSize _ 13200; new.imageFSize _ 10200; }; IF mouseButton = yellow THEN { new.nColors _ 1; IF shift THEN {new.sResolution _ new.fResolution _ Real.RoundLI[new.sResolution*versatecExpansion]}; }; IF data.pdOptions = NIL THEN { data.pdOptions _ new; IF NOT viewRecBuggy THEN [] _ ViewRec.ViewRef[agg: new, otherStuff: NIL, viewerInit: [name: "PD File Options", column: right]]; } ELSE data.pdOptions^ _ new^; data.log.PutF["\nOptions: %g\n", IO.refAny[new]]; }; Do[SetPDOptions, NARROW[clientData]]; }; PrintProc: Menus.MenuProc = { Do[PrintPage, NARROW[clientData]]; }; PrintAllProc: Menus.MenuProc = { Do[PrintAll, NARROW[clientData]]; }; NextProc: Menus.MenuProc = { Next: PROC[data: Data] = { n: NAT = data.pageNumber; count: NAT = IPExtras.PageCount[data.state]; SELECT mouseButton FROM red, yellow => { IF n { IF n>1 THEN { data.pageNumber _ n-1; PaintPageViewer[data]; }; }; ENDCASE; }; Do[Next, NARROW[clientData]]; }; WriteProc: Menus.MenuProc = { Write: PROC[data: Data] = { master: ROPE = Extend[ViewerTools.GetContents[data.masterField], ".Interpress"]; written: ROPE = Extend[ViewerTools.GetContents[data.writtenField], ".Interpress"]; log: STREAM = data.log; Dot: PROC = { log.PutChar['.] }; log.PutRope[IO.PutFR["%g -> %g ", IO.rope[master], IO.rope[written]]]; IPUtils.ToWritten[master, written, Dot]; log.PutRope["done\n"]; }; Do[Write, NARROW[clientData]]; }; ReadProc: Menus.MenuProc = { Read: PROC[data: Data] = { master: ROPE = Extend[ViewerTools.GetContents[data.masterField], ".Interpress"]; written: ROPE = Extend[ViewerTools.GetContents[data.writtenField], ".Interpress"]; log: STREAM = data.log; Dot: PROC = { log.PutChar['.] }; log.PutRope[IO.PutFR["%g -> %g ", IO.rope[written], IO.rope[master]]]; IPUtils.ToEncoded[written, master, Dot]; log.PutRope["done\n"]; }; Do[Read, NARROW[clientData]]; }; <> <> <> <> <> <> <<{ IPUtils.RopeToMaster[selection, "Selection.Interpress" ! ANY => GOTO Fail];>> <> <> < log.PutRope["failed\n"];>> <<};>> <<};>> <> <<};>> MakeRule: PROC[data: Data, height: NAT] = { rule: Rules.Rule _ Rules.Create[ [ -- create a horizontal rule to separate sections parent: data.outer, wy: data.height, ww: data.outer.cw, wh: height ]]; Containers.ChildXBound[data.outer, rule]; data.height _ rule.wy + rule.wh + lineLeading; -- spacing after rule }; TSOpen: PROC[viewer: Viewer] RETURNS[STREAM] = { in, out: STREAM; [in: in, out: out] _ ViewerIO.CreateViewerStreams[name: NIL, viewer: viewer, backingFile: NIL, editedStream: FALSE]; in.Close[]; RETURN[out]; }; MakeLogPart: PROC[data: Data, height: NAT] = { viewer: Viewer = ViewerOps.CreateViewer[ flavor: $Typescript, info: [parent: data.outer, wx: 0, ww: totalWidth, wy: data.height, wh: height, scrollable: TRUE, border: FALSE] ]; Containers.ChildXBound[data.outer, viewer]; Containers.ChildYBound[data.outer, viewer]; data.logViewer _ viewer; data.log _ TSOpen[viewer]; -- open an output stream on the typescript data.height _ viewer.wy + viewer.wh + lineLeading; -- spacing after typescript }; buttonBorders: BOOL _ TRUE; MakeFilePart: PROC[data: Data] = { middle: NAT = totalWidth/2; rightEdge: NAT = totalWidth; x: NAT _ margin; -- current x y: NAT _ data.height; -- current y container: Viewer = data.outer; AddButton: PROC[name: ROPE, proc: Buttons.ButtonProc] RETURNS[Button] = { button: Button = Buttons.Create[ info: [parent: container, name: name, wx: x, wy: y, wh: lineHeight, border: buttonBorders], proc: proc, clientData: data ]; x _ button.wx+button.ww+entryHSpace; RETURN[button]; }; AddPrompt: PROC[name: ROPE, proc: Buttons.ButtonProc] RETURNS[Button] = { button: Button = Buttons.Create[ info: [parent: container, name: name, wx: x, wy: y, wh: lineHeight, border: FALSE], proc: proc, clientData: data ]; x _ button.wx+button.ww; -- no extra space RETURN[button]; }; AddField: PROC[nextX: NAT] RETURNS[Viewer] = { field: Viewer = ViewerTools.MakeNewTextViewer[ info: [parent: container, wx: x, wy: y+1, ww: nextX-entryHSpace-x, wh: lineHeight, scrollable: TRUE, border: FALSE] ]; x _ nextX; RETURN[field]; }; NextLine: PROC = { y _ y+lineHeight+lineLeading; x _ margin; }; data.masterButton _ AddPrompt["Master:", MasterPrompt]; data.masterField _ AddField[rightEdge]; NextLine[]; data.writtenButton _ AddPrompt["Written:", WrittenPrompt]; data.writtenField _ AddField[rightEdge]; NextLine[]; data.height _ y; }; MasterPrompt: Buttons.ButtonProc = { data: Data = NARROW[clientData]; IF mouseButton=blue THEN ViewerTools.SetContents[data.masterField, NIL]; ViewerTools.SetSelection[data.masterField]; -- force the selection }; WrittenPrompt: Buttons.ButtonProc = { data: Data = NARROW[clientData]; IF mouseButton=blue THEN ViewerTools.SetContents[data.writtenField, NIL]; ViewerTools.SetSelection[data.writtenField]; -- force the selection }; PagePrompt: Buttons.ButtonProc = { data: Data = NARROW[clientData]; IF mouseButton=blue THEN ViewerTools.SetContents[data.pageField, NIL]; ViewerTools.SetSelection[data.pageField]; -- force the selection }; PutLine: PROC[data: Data, rope: ROPE] = { log: STREAM = data.log; log.PutRope[rope]; log.PutChar['\n]; }; PaintPage: ViewerClasses.PaintProc = { <<[self: Viewer, context: Graphics.Context, whatChanged: REF ANY, clear: BOOL]>> data: Data = NARROW[self.data]; IF whatChanged=$SetView THEN { display: Imager.Context ~ data.display; ImagerBridge.SetViewFromGraphicsContext[display, context]; Imager.Reset[display]; }; }; pageIcon: Icons.IconFlavor = Icons.NewIconFromFile["Interpress.icons", 2]; pageClass: ViewerClasses.ViewerClass = NEW[ViewerClasses.ViewerClassRec _ [ paint: PaintPage, icon: pageIcon]]; <<>> <> ViewerOps.RegisterViewerClass[$Page, pageClass]; <<>> <> Commander.Register[key: "Interpress", proc: MakeIPTool, doc: "Create an Interpress tool" ]; }.