XNSPrintCommandsImpl.mesa
Copyright Ó 1985, 1986, 1987, 1989, 1990 by Xerox Corporation. All rights reserved.
Russ Atkinson, April 2, 1985 4:22:08 pm PST
Bill Jackson (bj) April 24, 1990 5:08:27 pm PDT
Demers, June 6, 1986 3:09:39 pm PDT
Tim Diebert: November 27, 1987 8:54:48 am PST
Eric Nickell, October 8, 1987 2:58:13 pm PDT
Rick Beach, November 28, 1987 12:54:13 pm PST
gbb February 15, 1989 5:57:50 pm PST
Dave Rumph, March 13, 1990 6:32:47 pm PST
Swinehart, April 20, 1990 3:36:40 pm PDT
Willie-s, September 10, 1991 11:58 am PDT
DIRECTORY
Args USING [Arg, ArgsGet, Error, NArgs],
Commander USING [CommandProc, Register],
CommanderOps USING [ArgumentVector, Failed, Parse],
FileNames USING [ResolveRelativePath],
IO USING [bool, PutF, PutFR, rope, STREAM],
Process USING [CheckForAbort, Pause, SecondsToTicks],
Rope USING [Concat, Equal, Length, ROPE],
PrintingP4V3Aux,
SimpleFeedback USING [Append],
XNSPrint;
XNSPrintCommandsImpl: CEDAR PROGRAM
IMPORTS Args, Commander, CommanderOps, FileNames, IO, PrintingP4V3Aux, Process, Rope, SimpleFeedback, XNSPrint ~ {
OPEN PrintingAux: PrintingP4V3Aux;
ROPE: TYPE ~ Rope.ROPE;
Commander Constants
FaxIPMaster: ROPE ~ "FaxIPMaster";
faxdoc: ROPE ~ "<IPMaster> [-t <telephone number> -c <copies> -h <serviceName> -1 -2 -f <firstPageNumber> -l <lastPageNumber>]\nSend a master through an XNS based server to a remote FAX machine.\nSwitches:\n -t <telephone number> FAX phone number\n -c <copies> print multiple copies\n -h <serviceName> print thru service\n -1 print one-sided\n -2 print two-sided\n -f <firstPageNumber>\n -l <lastPageNumber>";
faxusage: ROPE ~ Rope.Concat["Usage: FaxIPMaster ", faxdoc];
GetPrintStatus: ROPE = "GetPrintStatus";
statusdoc: ROPE = "{Printer}*\nFind out the status of an XNS based printer.";
statususage: ROPE = Rope.Concat["Usage: GetPrintStatus ", statusdoc];
GetPrintProperties: ROPE = "GetPrintProperties";
propdoc: ROPE = "{Printer}*\nFind out the properties of an XNS based printer.\n";
propusage: ROPE = Rope.Concat["Usage: GetPrintProperties ", propdoc];
SendIPMaster: ROPE ~ "SendIPMaster";
senddoc: ROPE ~ "<IPMaster> [-1 -2 -a -b -s -c <copies> -h <serviceName> -f <firstPageNumber> -l <lastPageNumber> -m <message>]\nTransmit a master to an XNS based printer.\nSwitches:\n -1 print one-sided\n -2 print two-sided\n -a correct color (Lamming-Rhodes; includes -b)\n -b balance grays\n -s staple output\n -c <copies> print multiple copies\n -f <firstPageNumber>\n -h <serviceName> print on that service\n -l <lastPageNumber> -m <message> include parameter (possibly quoted) in printer message field";
sendusage: ROPE ~ Rope.Concat["Usage: SendIPMaster ", senddoc];
Commander Procs
GetPrintPropertiesProc: Commander.CommandProc ~ {
ENABLE {
CommanderOps.Failed => { msg ← errorMsg; GO TO Failed };
XNSPrint.Error => { msg ← Sensible[problem, explanation]; GO TO Failed };
};
argsProcessed: NAT ← 0;
argv: CommanderOps.ArgumentVector ← CommanderOps.Parse[cmd: cmd];
out: IO.STREAM ~ cmd.out;
CheckProperties: PROC [arg: ROPE] ~ {
service: ROPE;
properties: XNSPrint.Properties;
argsProcessed ← argsProcessed + 1;
Process.CheckForAbort[];
[service, properties] ← XNSPrint.GetPrinterProperties[arg];
IO.PutF[out, " Service: [%g]\n Staple: %g, TwoSided: %g\n Media: ",
IO.rope[service],
IO.bool[properties.staple],
IO.bool[properties.twoSided]
];
IF ( properties.media # NIL ) THEN DisplayMediaList[out, properties.media];
};
FOR i: NAT IN [1..argv.argc) DO
printerName: ROPE ~ argv[i];
Process.CheckForAbort[];
IF (Rope.Length[printerName] = 0) THEN LOOP;
CheckProperties[printerName];
ENDLOOP;
SELECT argsProcessed FROM
0 => {
context: XNSPrint.Context;
context ← XNSPrint.GetDefaults[];
IF (context.printerName = NIL)
THEN msg ← propusage
ELSE CheckProperties[context.printerName];
};
ENDCASE => { NULL };
EXITS
Failed => {result ← $Failure};
};
GetPrintStatusProc: Commander.CommandProc ~ {
ENABLE {
CommanderOps.Failed => { msg ← errorMsg; GO TO Failed };
XNSPrint.Error => { msg ← Sensible[problem, explanation]; GO TO Failed };
};
argsProcessed: NAT ← 0;
argv: CommanderOps.ArgumentVector ← CommanderOps.Parse[cmd: cmd];
out: IO.STREAM ~ cmd.out;
CheckPrinter: PROC [arg: ROPE] = {
service: ROPE;
status: XNSPrint.PrinterStatus;
argsProcessed ← argsProcessed + 1;
Process.CheckForAbort[];
[service, status] ← XNSPrint.GetPrinterStatus[arg];
IO.PutF[out, " Service: [%g]\n Spooler: %g, Formatter: %g, Printer: %g\n Media: ",
IO.rope[service],
IO.rope[PrintingAux.ExposeSpoolerStatus[status.spooler, 0]],
IO.rope[PrintingAux.ExposeFormatterStatus[status.formatter, 0]],
IO.rope[PrintingAux.ExposeMarkingEngineStatus[status.printer, 0]]
];
IF ( status.media # NIL ) THEN DisplayMediaList[out, status.media];
};
FOR i: NAT IN [1..argv.argc) DO
printerName: ROPE ~ argv[i];
Process.CheckForAbort[];
IF (Rope.Length[printerName] = 0) THEN LOOP;
CheckPrinter[printerName];
ENDLOOP;
SELECT argsProcessed FROM
0 => {
context: XNSPrint.Context;
context ← XNSPrint.GetDefaults[];
IF (context.printerName = NIL)
THEN msg ← statususage
ELSE CheckPrinter[context.printerName];
};
ENDCASE => NULL;
EXITS
Failed => {result ← $Failure};
};
FaxMasterProc: Commander.CommandProc ~ {
ENABLE {
XNSPrint.Error => { msg ← Sensible[problem, explanation]; GO TO Failed };
};
context: XNSPrint.Context;
request: XNSPrint.PrintRequest;
ok: BOOLTRUE; fullFName, exp: ROPENIL;
out: IO.STREAM ~ cmd.out;
name, phone, copies, host, oneSided, twoSided, first, last, pages: Args.Arg;
FixUpPhone: PROC [in: ROPE] RETURNS [out: ROPENIL] ~ {
out ← IO.PutFR["//%g//", IO.rope[in]];
};
IF Args.NArgs[cmd] = 0 THEN RETURN[$Failure, faxusage];
[name, phone, copies, host, oneSided, twoSided, first, last, pages] ← Args.ArgsGet[cmd,
"%s-t%s-c%i-h%s-1%b-2%b-f%i-l%i-p%i"
! Args.Error => {ok ← FALSE; CONTINUE}];
IF NOT ok THEN RETURN[$Failure, "Command syntax error."];
context ← XNSPrint.GetDefaults[];
IF copies.ok THEN context.copyCount ← copies.int;
IF host.ok THEN context.printerName ← host.rope;
IF phone.ok THEN context.message ← FixUpPhone[phone.rope];
IF twoSided.ok AND twoSided.bool THEN context.twoSided ← TRUE;
IF oneSided.ok AND oneSided.bool THEN context.twoSided ← FALSE;
IF first.ok THEN context.pageFirst ← first.int;
IF last.ok THEN context.pageLast ← last.int;
IF pages.ok THEN context.pageLast ← context.pageFirst+pages.int;
name.rope ← FileNames.ResolveRelativePath[name.rope];
fullFName ← name.rope; -- FixUpFilename[name.rope, FALSE];
IO.PutF[out, " Sending %s to %s",
IO.rope[fullFName],
IO.rope[context.printerName]
];
Process.CheckForAbort[];
request ← XNSPrint.PrintFromFile[name.rope, context, AllDone];
IO.PutF[out, "\n Service: [%g]\n RequestID: %g\n",
IO.rope[request.distinguishedName],
IO.rope[PrintingAux.ExposeRequestID[request.requestID, 0]]
];
EXITS
Failed => {result ← $Failure};
};
SendMasterProc: Commander.CommandProc ~ {
ENABLE {
XNSPrint.Error => { msg ← Sensible[problem, explanation]; GO TO Failed };
};
context: XNSPrint.Context;
request: XNSPrint.PrintRequest;
ok: BOOLTRUE; fullFName, exp: ROPENIL;
out: IO.STREAM ~ cmd.out;
name, copies, host, oneSided, twoSided, first, last, pages, colorCorr, grayBal, message, stapled: Args.Arg;
IF ( FALSE ) THEN {
[result, msg] ← GetPrintStatusProc[cmd];
IF ( result = $Failure ) THEN RETURN[$Failure, msg];
};
IF Args.NArgs[cmd] = 0 THEN RETURN[$Failure, sendusage];
[name, copies, host, oneSided, twoSided, first, last, pages, colorCorr, grayBal, message, stapled] ← Args.ArgsGet[cmd,
"%s-c%i-h%s-1%b-2%b-f%i-l%i-p%i-a%b-b%b-m%s-s%b"
! Args.Error => {ok ← FALSE; CONTINUE}];
IF NOT ok THEN RETURN[$Failure, "Command syntax error."];
context ← XNSPrint.GetDefaults[];
context.stapled ← FALSE;
IF copies.ok THEN context.copyCount ← copies.int;
IF host.ok THEN context.printerName ← host.rope;
IF twoSided.ok AND twoSided.bool THEN context.twoSided ← TRUE;
IF oneSided.ok AND oneSided.bool THEN context.twoSided ← FALSE;
IF first.ok THEN context.pageFirst ← first.int;
IF last.ok THEN context.pageLast ← last.int;
IF pages.ok THEN context.pageLast ← context.pageFirst+pages.int;
IF message.ok THEN context.message ← message.rope;
IF stapled.ok AND stapled.bool THEN context.stapled ← TRUE;
IF grayBal.ok THEN context.message ←
context.message.Concat["GrayBalanceThisMaster: TRUE\n"];
IF colorCorr.ok THEN context.message ←
context.message.Concat["ColorCorrectThisMaster: TRUE\n"];
Note: colorCorr currently is a hack to be able to switch it on and off during research. Once it will work, the switch will disappear and servers will always perform color correction. Giordano Beretta November 4, 1988 10:08:19 am PST.
name.rope ← FileNames.ResolveRelativePath[name.rope];
fullFName ← name.rope; -- FixUpFilename[name.rope, FALSE];
IO.PutF[out, " Sending %s to %s",
IO.rope[fullFName],
IO.rope[context.printerName]
];
Process.CheckForAbort[];
request ← XNSPrint.PrintFromFile[name.rope, context, AllDone !
XNSPrint.Error => {
IF problem=serviceRetry OR
(problem=service AND Rope.Equal[s1: explanation, s2: "Spooling Queue Full"]) OR
(problem=connection AND Rope.Equal[s1: explanation, s2: "communication failure"])
THEN {
Process.CheckForAbort[];
Process.Pause[Process.SecondsToTicks[5]];
IO.PutF[stream: out, format: " ... %lRETRY%l", v1: [rope["k"]], v2: [rope["K"]]];
RETRY;
}
}];
IO.PutF[out, "\n Service: [%g]\n RequestID: %g\n",
IO.rope[request.distinguishedName],
IO.rope[PrintingAux.ExposeRequestID[request.requestID, 0]]
];
EXITS
Failed => {result ← $Failure};
};
Helper Procs
AllDone: XNSPrint.StatusChangedProc ~ {
name: ROPE ← PrintingAux.ExposeInterpressMasterStatus[request.lastStatus.status, 0];
msg: ROPEIO.PutFR["print request: %g, status: (%g)",
IO.rope[request.fileName],
IO.rope[name]
];
SELECT request.lastStatus.status FROM
pending,
inProgress => {
SimpleFeedback.Append[$XNSPrintingUI, oneLiner, $info, msg];
};
completed,
completedWithWarning,
unknown,
rejected,
aborted,
canceled,
held => {
SimpleFeedback.Append[$XNSPrintingUI, oneLiner, $info, msg];
XNSPrint.UnRegisterPrintRequest[request];
};
ENDCASE => { NULL };
};
DisplayMediaList: PROC [out: IO.STREAM, m: XNSPrint.Media] ~ {
FOR tail: XNSPrint.Media ← m, tail.rest WHILE ( tail # NIL ) DO
IO.PutF[out, IF (tail = m) THEN "[ [%g]" ELSE ", [%g]", IO.rope[tail.first]];
ENDLOOP;
IO.PutF[out, " ]\n"];
};
<<
FSErrorMsg: PROC [error: FS.ErrorDesc] RETURNS [ROPE] ~ {
RETURN[Rope.Concat[FSErrorMsgBrief[error], "\n"]];
};
FSErrorMsgBrief: PROC [error: FS.ErrorDesc] RETURNS [ROPE] ~ {
SELECT error.group FROM
lock => {
RETURN[" -- locked!"];
};
ENDCASE => {
IF (error.code = $unknownFile)
THEN RETURN [" -- not found!"]
ELSE RETURN[Rope.Concat["\n -- FS.Error: ", error.explanation]];
};
};
FixUpFilename: PROC [name: ROPENIL, copyFrom: BOOL] RETURNS [newName: ROPE] ~ {
body: ROPE;
platformHost: ROPE ← ThisMachine.Name[];
platformVolume: ROPE ← File.GetVolumeName[File.SystemVolume[]];
prefix: ROPE;
cp: FS.ComponentPositions;
[fullFName: newName, cp: cp] ← FS.ExpandName[name];
prefix ← Rope.Substr[newName, 0, 4];
body ← Rope.Substr[newName, 4, Rope.Length[newName]];
IF Rope.Equal[prefix, "[]<>"] THEN {
newName ← Rope.Cat["[", platformHost, "]<", platformVolume, ">"];
newName ← Rope.Cat[newName, body];
}
ELSE newName ← Rope.Cat[
"[",
IF copyFrom THEN
FSPseudoServers.TranslateForRead[Rope.Substr[newName, cp.server.start, cp.server.length]].first
ELSE
FSPseudoServers.TranslateForWrite[Rope.Substr[newName, cp.server.start, cp.server.length]],
"]<",
Rope.Substr[newName, cp.dir.start, Rope.Length[newName]]];
};
>>
Sensible: PROC [problem: XNSPrint.Problem, explanation: ROPE] RETURNS [msg: ROPE] ~ {
PROBLEM: ARRAY XNSPrint.Problem OF ROPE ~ ["connection", "file", "name", "protocol", "service", "serviceRetry", "stream", "unknown"];
p: ROPE ~ PROBLEM[problem];
msg ← IO.PutFR["XNSPrint.Error(%g): %g", IO.rope[p], IO.rope[explanation]];
};
Initialization
Init: PROC ~ {
Commander.Register[FaxIPMaster, FaxMasterProc, faxdoc];
Commander.Register[GetPrintProperties, GetPrintPropertiesProc, propdoc];
Commander.Register[GetPrintStatus, GetPrintStatusProc, statusdoc];
Commander.Register[SendIPMaster, SendMasterProc, senddoc];
};
Init[];
}.