PDPrinterClientImpl.mesa
Michael Plass, April 10, 1984 2:00:07 pm PST
Last Edited by: Pier, November 22, 1983 2:52 pm
DIRECTORY Basics, Commander, Convert, Rope,
IO,
FS, MessageWindow, PDInterpBasic, PDPrinterRpcControl, PDPrinter, PDPrinterClient, PieViewers,
RPC, LupineRuntime, Process, ViewerOps;
PDPrinterClientImpl:
CEDAR
PROGRAM
IMPORTS Commander, Convert, IO, FS, MessageWindow, PDPrinterRpcControl, PDPrinter, Rope, RPC, LupineRuntime, PieViewers, Process, ViewerOps
EXPORTS PDPrinterClient
ROPE: TYPE ~ Rope.ROPE;
mess: CARDINAL ← 0;
copiesFieldIndex: NAT ~ 10;
BinaryStreamOptions:
PROC
RETURNS [s:
FS.StreamOptions] ~ {
s ← FS.defaultStreamOptions;
s[tiogaRead] ← FALSE;
};
GetToken:
PROC [stream:
IO.
STREAM]
RETURNS [token:
ROPE ←
NIL] = {
token ← stream.GetTokenRope[Break ! IO.EndOfStream => CONTINUE].token;
};
Break:
PROC [char:
CHAR]
RETURNS [
IO.CharClass] = {
IF char = '← OR char = '; THEN RETURN [break];
IF char = ' OR char = ' OR char = ', OR char = '\n THEN RETURN [sepr];
RETURN [other];
};
IsInteger:
PROC [rope:
ROPE]
RETURNS [
BOOLEAN] ~ {
IF NOT rope.Length IN [1..3] THEN RETURN [FALSE];
FOR i:
INT
IN [0..rope.Length)
DO
IF rope.Fetch[i] NOT IN ['0..'9] THEN RETURN [FALSE];
ENDLOOP;
RETURN [TRUE];
};
NotAPDFile:
PUBLIC
ERROR ~
CODE;
CheckPassword:
PROC [word0:
CARDINAL] ~ {
IF word0 # 0AAAAH
THEN
ERROR NotAPDFile};
Print:
PUBLIC
PROC [file: Rope.
ROPE, server: Rope.
ROPE, copies:
NAT ← 1, report:
IO.
STREAM ←
NIL, createFeedbackViewer:
BOOLEAN ←
TRUE] ~
TRUSTED {
serverRName: Rope.ROPE = server.Concat[".auto"];
interfaceName: RPC.InterfaceName ← [instance: serverRName];
pageNo: INT ← 0;
ReportStatus:
SAFE
PROC [status: PDInterpBasic.Status, report:
IO.
STREAM ←
NIL] ~
CHECKED {
stream: IO.STREAM ← IF report = NIL THEN IO.ROS[] ELSE report;
SELECT status
FROM
constructingImage => stream.PutF[" [%g", IO.int[pageNo ← pageNo + 1]];
betweenPages => {IF pageNo > 0 THEN stream.PutChar[']]};
transmissionComplete => stream.PutRope[" done"];
ENDCASE => {stream.PutChar[' ]; stream.Put[IO.refAny[NEW[PDInterpBasic.Status ← status]]]};
IF report =
NIL
THEN {
MessageWindow.Append[IO.RopeFromROS[stream], mess MOD 4 = 0];
mess ← mess + 1;
};
};
stream:
IO.
STREAM ←
FS.StreamOpen[fileName: file, streamOptions: BinaryStreamOptions[]
!
FS.Error =>
TRUSTED {
s: IO.STREAM ← IO.ROS[];
s.PutRope["Unable to open PD file: "];
s.PutRope[error.explanation];
s.PutRope[" ("];
s.Put[IO.rope[file]];
s.PutRope[")"];
IF report =
NIL
THEN {
MessageWindow.Append[IO.RopeFromROS[s], TRUE];
MessageWindow.Blink[];
}
ELSE {
report.PutRope[IO.RopeFromROS[s]];
};
GOTO Quit;
}
];
response: PDPrinter.Response ← [nextWordIndex: 0, status: betweenPages, currentPage: 0];
dataBlock: PDPrinter.DataBlock;
oldStatus: PDInterpBasic.Status ← transmissionComplete;
bufferPointer: LONG POINTER ← @dataBlock.buffer;
pieViewer: PieViewers.PieViewer ← NIL;
fileSize: INT = stream.GetLength;
PDPrinterRpcControl.ImportInterface[interfaceName
!
RPC.ImportFailed => {
s: IO.STREAM ← IO.ROS[];
s.PutRope["Unable to access PDInterpControl: "];
s.Put[IO.refAny[NEW[RPC.ImportFailure ← why]]];
IF report =
NIL
THEN {
MessageWindow.Append[IO.RopeFromROS[s], TRUE];
MessageWindow.Blink[];
}
ELSE {
report.PutRope[IO.RopeFromROS[s]];
};
GOTO Quit;
}
];
IF createFeedbackViewer
THEN {
pieViewer ← PieViewers.Create[parent: NIL, diameter: 0, total: fileSize];
pieViewer.name ← file.Concat[" to "].Concat[server];
pieViewer.icon ← private;
};
BEGIN
ENABLE
UNWIND => {PDPrinterRpcControl.UnimportInterface[];
IO.Close[stream];
IF pieViewer #
NIL
THEN {ViewerOps.DestroyViewer[pieViewer]; pieViewer ←
NIL}};
WHILE response.nextWordIndex >= 0
DO
byteIndex: INT ← response.nextWordIndex*2;
bytesRead: INT ← 0;
bytesPerBlock: INT = PDPrinter.maxBlockSize*Basics.bytesPerWord;
stream.SetIndex[byteIndex];
bytesRead ← stream.UnsafeGetBlock[[bufferPointer, 0, bytesPerBlock]];
dataBlock.wordIndex ← response.nextWordIndex;
dataBlock.wordCount ← bytesRead/Basics.bytesPerWord;
IF (copiesFieldIndex-dataBlock.wordIndex)
IN [0..dataBlock.wordCount)
THEN {
dataBlock.buffer[copiesFieldIndex-dataBlock.wordIndex] ← copies;
};
IF byteIndex = 0 THEN CheckPassword[dataBlock.buffer[0]];
IF pieViewer # NIL THEN PieViewers.Set[pieViewer, fileSize-byteIndex];
response ← PDPrinter.TransmitBlock[dataBlock];
IF response.status # oldStatus
THEN {
ReportStatus[response.status, report];
oldStatus ← response.status;
};
ENDLOOP;
END;
IF pieViewer # NIL THEN PieViewers.Set[pieViewer, 0];
PDPrinterRpcControl.UnimportInterface[];
IO.Close[stream];
IF pieViewer # NIL THEN {ViewerOps.DestroyViewer[pieViewer]; pieViewer ← NIL}
EXITS Quit => NULL;
};
PeachCommand: Commander.CommandProc ~ {
cmdStream: IO.STREAM ← IO.RIS[cmd.commandLine];
server: ROPE ← GetToken[cmdStream];
copies: NAT ← 1;
DO token:
ROPE ← GetToken[cmdStream];
IF token.Length = 0 THEN EXIT;
IF IsInteger[token] THEN copies ← Convert.IntFromRope[token]
ELSE {
fileName: ROPE;
cp: FS.ComponentPositions;
[fileName, cp] ←
FS.ExpandName[token ! FS.Error => {
IF cmd.out = NIL THEN REJECT ELSE {cmd.out.PutRope[fileName]; cmd.out.PutRope[": "]; cmd.out.PutRope[error.explanation]; CONTINUE}
}];
IF fileName = NIL THEN LOOP;
IF cp.ext.length = 0
THEN {
fileName ← fileName.Replace[cp.ext.start, cp.ext.length, ".pd"];
};
IF cmd.out #
NIL
THEN {
cmd.out.PutRope["Sending "];
cmd.out.PutRope[fileName];
IF copies # 1
THEN {
cmd.out.PutF[" (%g copies)", IO.int[copies]];
};
cmd.out.PutRope[" to "];
cmd.out.PutRope[server];
cmd.out.PutRope[" . . ."];
};
Print[fileName, server, copies, cmd.out !
LupineRuntime.BindingError => {IF cmd.out # NIL THEN cmd.out.PutRope[" ."]; Process.Pause[Process.MsecToTicks[5000]]; RETRY};
NotAPDFile => {IF cmd.out # NIL THEN cmd.out.PutRope[" not a PD file"]; CONTINUE};
];
IF cmd.out #
NIL
THEN {
cmd.out.PutRope[";\n"];
};
};
ENDLOOP;
};
Commander.Register["Peach", PeachCommand, "Usage: Peach <Peach server> {[ <copies> ] <PD file name>}, e.g. Peach Melba my 2 foo bar 1 baz sends one copy of my.pd, 2 of foo.pd and bar.pd, and one of baz.pd" ];
END.