IPTool.mesa
Last edit by:
Doug Wyatt, April 28, 1983 1:22 pm
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: BOOLFALSE,
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
]];
build each (sub)viewer in turn
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<count THEN {
data.pageNumber ← n+1;
PaintPageViewer[data];
};
};
blue => {
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: BOOLTRUE;
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]];
Register the Interpress class of viewer with the Window Manager
ViewerOps.RegisterViewerClass[$Page, pageClass];
Register a command with the UserExec that will create an instance of this tool.
Commander.Register[key: "Interpress", proc: MakeIPTool,
doc: "Create an Interpress tool" ];
CreateTool[]; -- and create an instance
}.