DIRECTORY CrRPC USING [BulkDataCheckAbortProc, BulkDataSource, Handle], FS USING [Delete, Error, StreamOpen], IO USING [rope, card, Close, Flush, PutF, PutFR1, STREAM, Value], PrintingP4V3Aux USING [ExposePrintAttributes, ExposePrintOptions, ExposeRequestID], Rope USING [ROPE], PrintingP4V3; XNSPrintServiceImpl: CEDAR MONITOR IMPORTS FS, IO, PrintingP4V3Aux EXPORTS PrintingP4V3 ~ { OPEN PrintingP4V3; BulkDataSource: TYPE ~ CrRPC.BulkDataSource; Handle: TYPE ~ CrRPC.Handle; ROPE: TYPE ~ Rope.ROPE; properties: PrintingP4V3.PrinterProperties; printerStatus: PrintingP4V3.PrinterStatus; State: TYPE = {empty, spooling, spooled, printing, done}; maxQueue: CARDINAL = 10; QueueIndex: TYPE = [0 .. maxQueue); nextEmpty: QueueIndex _ 0; -- Next available. queue: PrintQueue; queueChanged: CONDITION; PrintQueue: TYPE = ARRAY QueueIndex OF PrintQueueEntry; PrintQueueEntry: TYPE = RECORD [ id: PrintingP4V3.RequestID _ [0, 0, 0, 0, 0], fileName: ROPE _ NIL, state: State _ empty, printAttributes: PrintingP4V3.PrintAttributes _ NIL, printOptions: PrintingP4V3.PrintOptions _ NIL ]; Logger: ENTRY PROC [format: Rope.ROPE _ NIL, v1, v2, v3, v4, v5: IO.Value _ [null[]]] ~ { fname: ROPE ~ "///Temp/Printer/Operations.log"; out: IO.STREAM _ FS.StreamOpen[fname, $append]; IO.PutF[out, format, v1, v2, v3, v4, v5]; IO.Flush[out]; IO.Close[out]; }; ConstructPrinterStatus: PROC [spoolerBusy, formatterBusy: BOOL] RETURNS [printerStatus: PrinterStatus] ~ { printerStatus _ NEW[ PrinterStatusObject[4] ]; TRUSTED {printerStatus.body[0] _ [spooler[IF spoolerBusy THEN available ELSE busy]]}; TRUSTED {printerStatus.body[1] _ [formatter[IF formatterBusy THEN available ELSE busy]]}; TRUSTED {printerStatus.body[2] _ [printer[busy]]}; TRUSTED {printerStatus.body[3] _ [media[ConstructMedia[]]]}; }; Busy: PUBLIC ERROR ~ CODE; ConnectionError: PUBLIC ERROR [problem: ConnectionProblem] ~ CODE; InsufficientSpoolSpace: PUBLIC ERROR ~ CODE; InvalidPrintParameters: PUBLIC ERROR ~ CODE; MasterTooLarge: PUBLIC ERROR ~ CODE; MediumUnavailable: PUBLIC ERROR ~ CODE; ServiceUnavailable: PUBLIC ERROR ~ CODE; SpoolingDisabled: PUBLIC ERROR ~ CODE; SpoolingQueueFull: PUBLIC ERROR ~ CODE; SystemError: PUBLIC ERROR ~ CODE; TooManyClients: PUBLIC ERROR ~ CODE; TransferError: PUBLIC ERROR [problem: TransferProblem] ~ CODE; Undefined: PUBLIC ERROR [problem: CARDINAL] ~ CODE; currentID: PrintingP4V3.RequestID _ [0, 0, 0, 0, 0]; GetNextID: ENTRY PROC [] RETURNS [id: PrintingP4V3.RequestID] = { ENABLE UNWIND => NULL; md: MACHINE DEPENDENT RECORD [a, b: CARDINAL]; i: CARD; md.a _ currentID[0]; md.b _ currentID[1]; i _ LOOPHOLE[md]; i _ i + 1; md _ LOOPHOLE[i]; currentID[0] _ md.a; currentID[1] _ md.b; RETURN [currentID]; }; GetPrinterProperties: PUBLIC PROC [h: Handle] RETURNS [properties: PrinterProperties] ~ { Logger["GetPrinterProperties called:\n"]; RETURN[properties]; }; ConvertToRequestStatus: PROC [s: State] RETURNS [PrintingP4V3.InterpressMasterStatus] = { RETURN [SELECT s FROM empty => unknown, spooled => pending, printing => inProgress, done => completed, ENDCASE => ERROR]; }; GetPrintRequestStatus: PUBLIC PROC [h: Handle, printRequestID: RequestID] RETURNS [status: RequestStatus] ~ TRUSTED { Logger["GetPrintRequestStatus called:\n"]; Logger[" printRequestID: %g\n", IO.rope[PrintingP4V3Aux.ExposeRequestID[printRequestID, 2]] ]; FOR i: QueueIndex IN QueueIndex DO IF queue[i].id = printRequestID THEN { status _ NEW[RequestStatusObject[1]]; status.body[0] _ [status[ConvertToRequestStatus[queue[i].state]]]; RETURN [status]; }; ENDLOOP; status _ NEW[RequestStatusObject[1]]; status.body[0] _ [status[unknown]]; RETURN [status]; }; GetPrinterStatus: PUBLIC PROC [h: Handle] RETURNS [status: PrinterStatus] ~ { Logger["GetPrinterStatus called:\n"]; RETURN[printerStatus]; }; FindQueueSlot: ENTRY PROC RETURNS [slot: QueueIndex] = { ENABLE UNWIND => NULL; FOR i: QueueIndex IN QueueIndex DO IF queue[i].state = empty OR queue[nextEmpty].state = done THEN { queue[i].state _ spooling; RETURN[i]; }; ENDLOOP; ERROR SpoolingQueueFull; }; Print: PUBLIC PROC [h: Handle, master: BulkDataSource, printAttributes: PrintAttributes, printOptions: PrintOptions] RETURNS [printRequestID: RequestID] ~ { current: QueueIndex; MarkQueued: ENTRY PROC = { ENABLE UNWIND => NULL; queue[current].state _ spooled; BROADCAST queueChanged; }; aborted, sendAbort: BOOL _ FALSE; out: IO.STREAM _ NIL; CheckAbort: CrRPC.BulkDataCheckAbortProc ~ {abort _ sendAbort}; { -- for exit Logger["Print called:\n"]; Logger[" printAttributes: %g\n", IO.rope[PrintingP4V3Aux.ExposePrintAttributes[printAttributes, 2]] ]; Logger[" printOptions: %g\n", IO.rope[PrintingP4V3Aux.ExposePrintOptions[printOptions, 2]] ]; printRequestID _ GetNextID[]; current _ FindQueueSlot[]; queue[current].id _ printRequestID; queue[current].state _ spooling; queue[current].printAttributes _ printAttributes; queue[current].printOptions _ printOptions; FS.Delete[queue[current].fileName ! FS.Error => CONTINUE]; out _ FS.StreamOpen[queue[current].fileName, $create]; aborted _ master[h, out, CheckAbort ! FS.Error => {sendAbort _ TRUE; GOTO Abort}]; IF out # NIL THEN IO.Close[out]; IF aborted THEN GOTO Abort; MarkQueued[]; EXITS Abort => { FS.Delete[queue[current].fileName ! FS.Error => CONTINUE]; queue[current].state _ empty; ERROR TransferError[aborted]; }; }; -- for exit }; ConstructPrinterProperties: PROC [] RETURNS [properties: PrinterProperties] ~ { properties _ NEW[ PrinterPropertiesObject[3] ]; TRUSTED { properties.body[0] _ [ppmedia[ConstructMedia[]]] }; TRUSTED { properties.body[1] _ [ppstaple[FALSE]] }; TRUSTED { properties.body[2] _ [pptwoSided[FALSE]] }; }; ConstructMedia: PROC [] RETURNS [media: Media] ~ { media _ NEW[ MediaObject[1] ]; TRUSTED { media.body[0] _ [paper[paper: [knownSize[usLetter]]]] }; }; SetUpQueue: PROC [] = { FOR i: QueueIndex IN QueueIndex DO queue[i].fileName _ IO.PutFR1["///Spool/File%2g.ip", IO.card[i]]; ENDLOOP; }; Init: ENTRY PROC ~ { properties _ ConstructPrinterProperties[]; printerStatus _ ConstructPrinterStatus[spoolerBusy: FALSE, formatterBusy: FALSE]; SetUpQueue[]; }; Init[]; }... ΞXNSPrintServiceImpl.mesa Copyright Σ 1986, 1987 by Xerox Corporation. All rights reserved. Tim Diebert: January 9, 1987 1:24:20 pm PST Copied Types Global vars PrintQueue I/O Procs Helper PROCs Errors Active Procs REPORTS [ServiceUnavailable, SystemError, Undefined] REPORTS [ServiceUnavailable, SystemError, Undefined] REPORTS [ServiceUnavailable, SystemError, Undefined] REPORTS [Busy, ConnectionError, InsufficientSpoolSpace, InvalidPrintParameters, MasterTooLarge, MediumUnavailable, ServiceUnavailable, SpoolingDisabled, SpoolingQueueFull, SystemError, TooManyClients, TransferError, Undefined] Init Procs TRUSTED { media.body[n] _ [paper[otherSize[width: mm, length: 0]]] }; -- zero is infinity! Κ―˜codešœ™KšœB™BK™+K™—šΟk ˜ Kšœœ2˜=Kšœœ˜%Kšœœ( œ˜AKšœœ>˜SKšœœœ˜Kšœ ˜ —K˜šΟnœœ˜"Kšœœ˜Kšœ˜Kšœ˜—K™K™ ™Kšœœ˜,Kšœœ˜Kšœœœ˜—K˜™ K˜Kšœ*˜+Kšœ*˜*—K˜™ K˜Kšœœ.˜9Kšœ œ˜Kšœ œ˜#K˜KšœΟc˜.Kšœ˜Kšœ œ˜K˜Kšœ œœ œ˜7šœœœ˜ Kšœ-˜-Kšœ œœ˜K˜Kšœ0œ˜4Kšœ*˜-K˜K˜——K˜™ K™š žœœœœœœ˜YKšœœ$˜/Kšœœœœ˜/Kšœ'˜)Kšœ ˜Kšœ ˜Kšœ˜K˜——šœ ™ K˜šžœœœœ#˜jKšœœ˜.Kšœ#œ œ œ ˜UKšœ%œœ œ ˜YKšœ+˜2Kšœ5˜Kš ž œœœ œœ˜3K™—šœ ™ K˜Kšœ4˜4K˜šž œ œœ!˜AKšœœœ˜Kš œœ œœœœ˜7Kšœ)˜)Kšœœ˜K˜ Kšœœ˜Kšœ)˜)Kšœ ˜Kšœ˜—K˜šžœœœ œ$˜YKšœ-™4Kšœ)˜)Kšœ ˜K˜K˜—šžœœ œ*˜Yšœœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœœ˜—Kšœ˜—š žœœœ(œœ˜uKšœ.™5Kšœ*˜*šœ ˜ Kšœ9˜;Kšœ˜—šœœ ˜"šœœ˜&Kšœ œ˜%KšœB˜BKšœ ˜Kšœ˜—Kšœ˜—Kšœ œ˜%Kšœ#˜#Kšœ ˜K˜K˜—šžœœœ œ˜MKšœ-™4Kšœ%˜%Kšœ˜Kšœ˜K˜—šž œœœœ˜8Kšœœœ˜šœœ ˜"šœœœ˜AKšœ˜Kšœ˜ Kšœ˜—Kšœ˜—Kšœ˜Kšœ˜—K˜šžœœœcœ ˜œKšœΫ™βKšœ˜šž œœœ˜Kšœœœ˜Kšœ˜Kš œ˜Kšœ˜—Kšœœœ˜!Kšœœœœ˜Kšž œ5˜?šœŸ ˜ Kšœ˜šœ!˜!Kšœ@˜BKšœ˜—šœ˜Kšœ:˜