<> <> <> DIRECTORY Buttons USING [Button, ButtonProc, Create], Commander USING [CommandProc, Register], Containers USING [ChildXBound, Container, Create], Convert USING [ValueToRope], Graphics USING [Context, CopyContext], Icons USING [IconFlavor, NewIconFromFile], IO USING [Close, PutChar, PutRope, STREAM], IPBasic USING [State], IPControl USING [DoPage, OpenMaster, PageCount, SetErrorLog], IPImagerOps USING [SetContext], IPMisc USING [RopeToMaster, ToEncoded, ToWritten], Menus USING [AppendMenuEntry, CreateEntry, CreateMenu, Menu, MenuProc], Process USING [Pause, SecondsToTicks], Rope USING [Cat, Concat, Find, ROPE], Rules USING [Create, Rule], ViewerClasses USING [PaintProc, Viewer, ViewerClass, ViewerClassRec], ViewerIO USING [CreateViewerStreams], ViewerOps USING [CreateViewer, PaintViewer, RegisterViewerClass], ViewerTools USING [MakeNewTextViewer, GetContents, GetSelectionContents, SetContents, SetSelection]; IPTool: CEDAR MONITOR LOCKS data USING data: Data IMPORTS Buttons, Commander, Containers, Convert, Graphics, Icons, IO, IPControl, IPImagerOps, IPMisc, Menus, Process, Rope, Rules, ViewerIO, ViewerOps, ViewerTools = { -- Here is the layout of the tool -- --========================================================================-- -- Interpress -- --========================================================================-- -- Load Show Next Write Read LoadSelection -- --========================================================================-- -- Master: Test.Interpress Written: Test.IPWritten -- -- Page: 2 -- --========================================================================-- -- 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: IPBasic.State -- state of the Interpress interpreter ]; Lock: ENTRY PROC[data: Data] RETURNS[BOOL] = INLINE { IF data.busy THEN RETURN[FALSE] ELSE RETURN[data.busy _ TRUE]; }; Unlock: ENTRY PROC[data: Data] = INLINE { 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]; 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]; PutLine[data, "Interpress Tool of April 28, 1983"]; 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: "Write", proc: WriteProc, clientData: data] ]; Menus.AppendMenuEntry[menu: menu, entry: Menus.CreateEntry[name: "Read", proc: ReadProc, clientData: data] ]; Menus.AppendMenuEntry[menu: menu, entry: Menus.CreateEntry[name: "LoadSelection", proc: LoadSelectionProc, clientData: data] ]; RETURN[menu]; }; PaintPageViewer: PROC[data: Data] = { page: Viewer = data.page; master: ROPE = data.masterName; num: ROPE = Convert.ValueToRope[[unsigned[data.pageNumber]]]; page.name _ Rope.Cat[master, ", page ", num]; ViewerOps.PaintViewer[viewer: page, hint: all]; IPControl.DoPage[data.state, data.pageNumber]; }; Extend: PROC[name: ROPE, ext: ROPE] RETURNS[ROPE] = { RETURN[IF name.Find["."]<0 THEN name.Concat[ext] ELSE name]; }; LoadMaster: PROC[data: Data] = { name: ROPE = ViewerTools.GetContents[data.masterField]; file: ROPE = Extend[name, ".Interpress"]; log: STREAM = data.log; log.PutRope["Loading "]; log.PutRope[file]; log.PutRope[".\n"]; data.state _ IPControl.OpenMaster[file]; IPControl.SetErrorLog[data.state, log]; data.masterName _ name; data.pageNumber _ 1; }; Do: PROC[proc: PROC[Data], data: Data] = { IF Lock[data] THEN { proc[data ! UNWIND => Unlock[data]]; Unlock[data]; }; }; LoadProc: Buttons.ButtonProc = { Do[LoadMaster, NARROW[clientData]]; }; ShowProc: Menus.MenuProc = { Do[PaintPageViewer, NARROW[clientData]]; }; NextProc: Menus.MenuProc = { Next: PROC[data: Data] = { n: NAT = data.pageNumber; count: NAT = IPControl.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], ".IPWritten"]; log: STREAM = data.log; Dot: PROC = { log.PutChar['.] }; log.PutRope[Rope.Cat[master, " -> ", written, " "]]; { IPMisc.ToWritten[master, written, Dot ! ANY => GOTO Fail]; log.PutRope["ok\n"]; EXITS Fail => log.PutRope["failed\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], ".IPWritten"]; log: STREAM = data.log; Dot: PROC = { log.PutChar['.] }; log.PutRope[Rope.Cat[written, " -> ", master, " "]]; { IPMisc.ToEncoded[written, master, Dot ! ANY => GOTO Fail]; log.PutRope["ok\n"]; EXITS Fail => log.PutRope["failed\n"]; }; }; Do[Read, NARROW[clientData]]; }; LoadSelectionProc: Menus.MenuProc = { LoadSelection: PROC[data: Data] = { selection: ROPE = ViewerTools.GetSelectionContents[]; log: STREAM = data.log; ViewerTools.SetContents[data.masterField, "Selection"]; log.PutRope[Rope.Cat[" Parsing selection ..."]]; { IPMisc.RopeToMaster[selection, "Selection.Interpress" ! ANY => GOTO Fail]; log.PutRope["ok\n"]; LoadMaster[data]; EXITS Fail => log.PutRope["failed\n"]; }; }; Do[LoadSelection, NARROW[clientData]]; }; 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, ww: totalWidth, wy: data.height, wh: height, scrollable: TRUE, border: FALSE] ]; Containers.ChildXBound[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[middle]; data.writtenButton _ AddPrompt["Written:", WrittenPrompt]; data.writtenField _ AddField[rightEdge]; NextLine[]; data.pageButton _ AddPrompt["Page:", PagePrompt]; data.pageField _ AddField[middle]; 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 = { data: Data = NARROW[self.data]; state: IPBasic.State = data.state; IF state#NIL THEN { IPImagerOps.SetContext[state, Graphics.CopyContext[context]]; }; }; 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" ]; CreateTool[]; -- and create an instance }.