<> <> <> <> <> <> <> <> <> <> <> <> 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; <> FaxIPMaster: ROPE ~ "FaxIPMaster"; faxdoc: ROPE ~ " [-t -c -h -1 -2 -f -l ]\nSend a master through an XNS based server to a remote FAX machine.\nSwitches:\n -t FAX phone number\n -c print multiple copies\n -h print thru service\n -1 print one-sided\n -2 print two-sided\n -f \n -l "; 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 ~ " [-1 -2 -a -b -s -c -h -f -l -m ]\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 print multiple copies\n -f \n -h print on that service\n -l -m include parameter (possibly quoted) in printer message field"; sendusage: ROPE ~ Rope.Concat["Usage: SendIPMaster ", senddoc]; <> 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: BOOL _ TRUE; fullFName, exp: ROPE _ NIL; out: IO.STREAM ~ cmd.out; name, phone, copies, host, oneSided, twoSided, first, last, pages: Args.Arg; FixUpPhone: PROC [in: ROPE] RETURNS [out: ROPE _ NIL] ~ { 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: BOOL _ TRUE; fullFName, exp: ROPE _ NIL; 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"]; <> 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}; }; <> 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.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: 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]]; }; <> Init: PROC ~ { Commander.Register[FaxIPMaster, FaxMasterProc, faxdoc]; Commander.Register[GetPrintProperties, GetPrintPropertiesProc, propdoc]; Commander.Register[GetPrintStatus, GetPrintStatusProc, statusdoc]; Commander.Register[SendIPMaster, SendMasterProc, senddoc]; }; Init[]; }. <<>>