XNSPrintCommandsImpl.mesa
Copyright Ó 1985, 1986, 1987, 1989, 1990, 1992 by Xerox Corporation. All rights reserved.
Russ Atkinson, June 5, 1993 7:35 pm PDT
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, April 7, 1992 4:54 pm PDT
Michael Plass, June 2, 1993 3:31 pm PDT
DIRECTORY
Args USING [Arg, ArgsGet, Error, NArgs],
Commander USING [CommandProc, Register],
CommanderOps USING [ArgumentVector, Failed, Parse],
FileNames USING [ResolveRelativePath],
IO,
Process USING [CheckForAbort, Pause, SecondsToTicks],
Rope USING [Cat, Concat, Equal, Length, ROPE],
PrintingP4V3Aux,
SimpleFeedback USING [Append],
XNSPrint,
XNSPrintExtras;
XNSPrintCommandsImpl: CEDAR PROGRAM
IMPORTS Args, Commander, CommanderOps, FileNames, IO, PrintingP4V3Aux, Process, Rope, SimpleFeedback, XNSPrint, XNSPrintExtras ~ {
OPEN PrintingAux: PrintingP4V3Aux;
ROPE: TYPE ~ Rope.ROPE;
Commander Constants
FaxIPMaster: ROPE ~ "FaxIPMaster";
faxdoc: ROPE ~ "<IPMaster> [-t <telephone number> -c <copies> -h <serviceName> -0 -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 -0 leave plex unspecified\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> [-0 -1 -2 -a -b -s -c <copies> -h <serviceName> -f <firstPageNumber> -l <lastPageNumber> -m <message> -medium <medium>]\nTransmit a master to an XNS based printer.\nSwitches:\n -0 leave plex unspecified\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\n -medium <medium> paper size, e.g., -medium usLetter or -medium ([width~229, length~279])";
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.PutFL[out, " Service: [%g]\n Spooler: %g, Formatter: %g, Printer: %g\n Media: ",
LIST[ 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: BOOL ¬ TRUE; fullFName, exp: ROPE ¬ NIL;
out: IO.STREAM ~ cmd.out;
name, phone, copies, host, defaultPlex, oneSided, twoSided, first, last, pages: Args.Arg;
FixUpPhone: PROC [in: ROPE] RETURNS [out: ROPE ¬ NIL] ~ {
out ¬ IO.PutFR1["//%g//", IO.rope[in]];
};
IF Args.NArgs[cmd] = 0 THEN RETURN[$Failure, faxusage];
[name, phone, copies, host, defaultPlex, oneSided, twoSided, first, last, pages] ¬ Args.ArgsGet[cmd,
"%s-t%s-c%i-h%s-0%b-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 defaultPlex.ok AND defaultPlex.bool THEN XNSPrintExtras.SetPlex[context, $default];
IF twoSided.ok AND twoSided.bool THEN XNSPrintExtras.SetPlex[context, $simplex];
IF oneSided.ok AND oneSided.bool THEN XNSPrintExtras.SetPlex[context, $duplex];
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: BOOL ¬ TRUE; fullFName, exp: ROPE ¬ NIL;
out: IO.STREAM ~ cmd.out;
name, copies, host, defaultPlex, oneSided, twoSided, first, last, pages, colorCorr, grayBal, message, stapled, medium: 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, defaultPlex, oneSided, twoSided, first, last, pages, colorCorr, grayBal, message, stapled, medium] ¬ Args.ArgsGet[cmd,
"%s-c%i-h%s-0%b-1%b-2%b-f%i-l%i-p%i-a%b-b%b-m%s-s%b-medium%s"
! 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;
XNSPrintExtras.SetPlex[context, $default];
IF twoSided.ok AND twoSided.bool THEN XNSPrintExtras.SetPlex[context, $duplex];
IF oneSided.ok AND oneSided.bool THEN XNSPrintExtras.SetPlex[context, $simplex];
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 XNSPrintExtras.SetStapling[context, $stapled];
IF medium.ok THEN {
[] ¬ XNSPrint.GetPrinterProperties[context.printerName]; -- This loads the media list with all the sizes this printer knows about.
IF XNSPrint.GetPaperDimensions[medium.rope].width = 0 THEN {
CommanderOps.Failed[Rope.Cat["Unknown medium: ", medium.rope, "; use GetPrintProperties to list the known media for this printer"]];
};
context.mediumHint ¬ medium.rope;
};
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[];
NoteContext[context];
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};
};
NoteContext: PROC [c: XNSPrint.Context] = {
RRA: A great place to plant a breakpoint!
IF c = NIL THEN ERROR;
};
Helper Procs
AllDone: XNSPrint.StatusChangedProc ~ {
name: ROPE ¬ PrintingAux.ExposeInterpressMasterStatus[request.lastStatus.status, 0];
msg: ROPE ¬ IO.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.PutF1[out, IF (tail = m) THEN "[ [%g]" ELSE ", [%g]", IO.rope[tail.first]];
ENDLOOP;
IO.PutRope[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: ROPE ¬ NIL, 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[];
}.