DIRECTORY
BasicTime USING [Update, GetUniversalID, GMT, SecondsSinceEpoch],
DecomposerControl USING [DocumentInProgress, FreeDecomposeObject, NoticeNewFonts, Start, Stop, Stopped],
ForwardingControl USING [Start, Stop, Stopped],
Heap USING [FreeNode, MakeNode],
MarkerControl USING [EngineSpecific],
MergeControl USING [Start, Stop, Stopped],
MsgOps USING [FilingErrToMsg],
NSDataStream USING [Abort, Aborted, Handle, OperateOnSource, Source, SourceStream],
NSFile USING [Attribute, Attributes, Close, Error, ErrorRecord, GetAttributes, GetAttributesRecord, Handle, lastPosition, noSelections, nullHandle, ReleaseAttributesRecord, Replace, Selections, Session],
NSName USING [Name],
NSPrintCourier USING [ExportRemoteProgram, UnexportRemoteProgram],
NSString USING [AppendCharacter, AppendString, Character, EquivalentStrings, EqualCharacter, nullString, ScanForCharacter, String, StringBoundsFault, StringFromMesaString],
PaperHandling USING [TwoPaperSizes],
PaperTypes USING [PaperMMDimension, PaperSize],
PaperTypesExtras USING [nullPaper],
PrincOps USING [BYTE],
PrintQueue USING [CopyStringIn, CopyQueueObject, LocateHandle, maxFaxPhoneNos, maxPhoneNoLength, nilQueueObjectHandle, ObjectStatus, Previous, QueueObject, QueueObjectHandle, QueueStage, Requeue],
PrintQueueExtras USING [GetQueueObject],
Process USING [Detach],
PSAsyncMsg USING [Expand1AndPutString, ExpandArrayAndPutString, PutMesaString],
PSCommand USING [allDocuments, DocumentAttributes, DocumentAttrRecord, DocumentFilter, DocumentID, DocumentParameters, DocumentProc, DocumentStatus, Error, ErrorRecord, FaxTransmitData, noDocuments, nullDocumentID, SimpleDocStatus],
PSCommandInternal USING [commandHeap, currentCondition, fontsNoticed, markerProcs, RotateFonts90, state, stateSpace, testPatternsNoticed],
PSState USING [SpoolerState],
PSVolume USING [GetDefaultSession],
QueueControl USING [WaitAbortQueueEmpty],
QueueFile USING [CreateError, CreateTempFile, Delete, InsufficientPages, MakePermanent],
Space USING [ForceOut],
SpoolControl USING [ConnectionClosed, Error, ErrorTypes, FilterConnection, Start, Stop, Stopped, Suspend],
Stream USING [Delete],
String USING [AppendDecimal, AppendLongDecimal],
TestPattern USING [CatalogTPs],
Time USING [Append, AppendCurrent, Unpack];
PSCommandAImpl:
CEDAR PROGRAM
IMPORTS BasicTime, DecomposerControl, ForwardingControl, Heap, MergeControl, MsgOps, NSDataStream, NSFile, NSPrintCourier, NSString, PrincOps, PrintQueue, PrintQueueExtras, Process, PSAsyncMsg, PSCommand, PSCommandInternal, PSVolume, QueueControl, QueueFile, Space, SpoolControl, Stream, String, TestPattern, Time
EXPORTS PSCommand, PSCommandInternal
SHARES SpoolControl = BEGIN
OPEN PSCommandInternal;
session: NSFile.Session = PSVolume.GetDefaultSession[];
nsNil: NSString.String = NSString.nullString;
Same as PSCommand.DocumentFilter except filters on PrintQueue.ObjectStatus:
QueueObjectFilter:
TYPE =
RECORD [
id: PSCommand.DocumentID ← PSCommand.nullDocumentID,
name: NSString.String ← nsNil,
sender: NSString.String ← nsNil,
status: PACKED ARRAY PrintQueue.ObjectStatus OF BOOLEAN ← ALL[FALSE]];
Error:
PUBLIC
ERROR [problem: PSCommand.ErrorRecord] =
CODE;
*********************************
PUBLIC PROCS:--
*********************************
*********************************
Queue/Document Operations:
*********************************
Enqueue:
PUBLIC
PROCEDURE [document: NSDataStream.Source, parameters: PSCommand.DocumentParameters]
RETURNS [documentID: PSCommand.DocumentID] = BEGIN
beginSpoolDate: BasicTime.GMT ← BasicTime.Update[];
file: NSFile.Handle;
attris: ARRAY [0..1) OF NSFile.Attribute ← [[position[NSFile.lastPosition]]];
qOH: PrintQueue.QueueObjectHandle;
why: PSCommand.ErrorRecord;
HandleNSFileFailure:
PROCEDURE [qOH: PrintQueue.QueueObjectHandle, error: NSFile.ErrorRecord] =
BEGIN
IF state.spoolerTrace # none
THEN
BEGIN
nsFileFailure: NSString.String = Str["--File Transfer Failed: <1>"L];
stringArray: ARRAY [0..1) OF NSString.String;
DisplayInitialSpoolInfo[qOH];
[stringArray[0],] ← MsgOps.FilingErrToMsg[error];
PSAsyncMsg.ExpandArrayAndPutString[nsFileFailure, DESCRIPTOR[stringArray]];
END;
qOH.currentStatus ← spoolFailure;
qOH.fileID ← QueueFile.Delete[qOH.fileID, file];
[] ← PrintQueue.Requeue[qOH: qOH, fromQueue: spooling, toQueue: aborted];
END; --HandleNSFileFailure
BEGIN
SpoolControl.FilterConnection[! SpoolControl.Error => {
why ← ConvertSpoolControlError[type]; GOTO SpoolControlError}];
[file, qOH] ← CreateSpoolFile[parameters !
UNWIND => SpoolControl.ConnectionClosed[]];
EXITS SpoolControlError => {
NSDataStream.OperateOnSource[document, AbortAndDeleteSourceStream];
ERROR PSCommand.Error[why]; };
END;
NSFile.Replace[file, document, , session
! NSFile.Error => {SpoolControl.ConnectionClosed[];
HandleNSFileFailure[qOH, error]; REJECT}];
SpoolControl.ConnectionClosed[];
QueueFile.MakePermanent[file,
DESCRIPTOR[attris]
! NSFile.Error => {HandleNSFileFailure[qOH, error]; REJECT}];
Process.Detach[FORK CompleteEnqueue[qOH, file, beginSpoolDate]]; --finish up queuing without keeping the client waiting
RETURN[qOH.uid];
END; --Enqueue
ListDocuments: PUBLIC SAFE PROCEDURE [proc: PSCommand.DocumentProc, filter: PSCommand.DocumentFilter ← PSCommand.allDocuments] =
ListDocuments lists the queue stage(s) corresponding to the statuses specified in the filter. Status types are defined in PSCommand and include: pending, inProgress, completed, completedWithWarnings, unknown, rejected, aborted, canceled and held. The statuses completedWithWarnings, unknown and held are not currently supported.
The queues containing the newest documents are listed first. The procedure ListQueueStage goes through the documents on the queue stage newest first and determines which ones satisfy the rest of the filter and calls the proc passing the attributes of such documents.
BEGIN
continue: BOOLEAN ← TRUE;
qObjFilter: QueueObjectFilter ← [];
scratchQOH: PrintQueue.QueueObjectHandle ← NIL;
scratchDocAttributes: PSCommand.DocumentAttributes ← NIL;
scratchFaxMitData: LONG DESCRIPTOR FOR ARRAY OF PSCommand.FaxTransmitData ← DESCRIPTOR[NIL, 0];
IF filter = PSCommand.noDocuments THEN RETURN;
QObjFilterFromClientFilter[@filter, @qObjFilter];
Allocate space used by ListQueueStage proc...
scratchQOH ← PrintQueueExtras.GetQueueObject[commandHeap];
scratchDocAttributes ← commandHeap.NEW[PSCommand.DocumentAttrRecord.fax495]; --allocate enough space for the largest variant
scratchFaxMitData ←
DESCRIPTOR[Heap.MakeNode[
commandHeap, SIZE[PSCommand.FaxTransmitData] * PrintQueue.maxFaxPhoneNos], PrintQueue.maxFaxPhoneNos];
BEGIN --extra begin/end for exits statement at end of proc
The filter 'allDocuments' lists all 15 queue stages, including the temp queue, which is otherwise never listed.
IF filter = PSCommand.allDocuments
THEN
BEGIN
--list all queues
noOfQueues: CARDINAL = 18;
queueStage:
ARRAY [0..noOfQueues)
OF PrintQueue.QueueStage ← [
spooling, spooledNormal, bannerOnly, tpSpooled, decomposing, decomposed,
tpDecomposed, retransmit, marking, marked, merging, merged,
tpMerged, forwarding, forwarded, aborted, temp, inactive];
FOR i:
CARDINAL
IN [0..noOfQueues)
DO
continue ← ListQueueStage[
queueStage[i], proc, qObjFilter, scratchQOH,
scratchDocAttributes, scratchFaxMitData];
IF NOT continue THEN GOTO Done;
ENDLOOP;
END
ELSE
BEGIN
--List queue stages corresponding to statuses specified:
If pending documents are to be listed, list in order the spooler working queue, spooler done queue, decomposer from queue, decomposer retry queue, decomposer banner only queue and test pattern spooled queue:
IF filter.status[pending]
THEN
BEGIN
noOfQueues: CARDINAL = 4;
queueStage:
ARRAY [0..noOfQueues)
OF PrintQueue.QueueStage ← [
spooling, spooledNormal, bannerOnly, tpSpooled];
FOR i:
CARDINAL
IN [0..noOfQueues)
DO
continue ← ListQueueStage[
queueStage[i], proc, qObjFilter, scratchQOH,
scratchDocAttributes, scratchFaxMitData];
IF NOT continue THEN GOTO Done;
ENDLOOP;
END;
If inProgress documents are to be listed, list in order the decomposer working queue, decomposer done queue, marker from queue, test pattern decomposed queue and marker working queue:
IF filter.status[inProgress]
THEN
BEGIN
noOfQueues: CARDINAL = 9;
queueStage:
ARRAY [0..noOfQueues)
OF PrintQueue.QueueStage ← [
decomposing, decomposed, tpDecomposed, retransmit, marking,
merging, merged, tpMerged, forwarding];
FOR i:
CARDINAL
IN [0..noOfQueues)
DO
continue ← ListQueueStage[
queueStage[i], proc, qObjFilter, scratchQOH,
scratchDocAttributes, scratchFaxMitData];
IF NOT continue THEN GOTO Done;
ENDLOOP;
END;
If completed, rejected, aborted or canceled documents are to be listed, list in order the marker done queue, abort queue and inactive queue:
IF filter.status[completed]
OR filter.status[rejected]
OR filter.status[aborted]
OR filter.status[canceled]
THEN
BEGIN
noOfQueues: CARDINAL = 4;
queueStage:
ARRAY [0..noOfQueues)
OF PrintQueue.QueueStage ← [
marked, forwarded, aborted, inactive];
FOR i:
CARDINAL
IN [0..noOfQueues)
DO
continue ← ListQueueStage[
queueStage[i], proc, qObjFilter, scratchQOH,
scratchDocAttributes, scratchFaxMitData];
IF NOT continue THEN GOTO Done;
ENDLOOP;
END;
END;
END;
commandHeap.FREE[@scratchQOH];
commandHeap.FREE[@scratchDocAttributes];
Heap.FreeNode[commandHeap, BASE[scratchFaxMitData]];
END; --ListDocuments
CancelDocument:
PUBLIC
PROCEDURE [documentID: PSCommand.DocumentID]
RETURNS [status: PSCommand.DocumentStatus] = BEGIN
Cannot currently cancel a document on spooling queue or temp queue.
What happens if, while we try to cancel a doc on an intermediate queue (e.g. spooled), the doc moves onto a working queue (e.g. decomposing)?
qOH: PrintQueue.QueueObjectHandle;
queueStage: PrintQueue.QueueStage;
[qOH, queueStage] ← PrintQueue.LocateHandle[documentID];
IF qOH = PrintQueue.nilQueueObjectHandle THEN ERROR Error[[documentNotFound[]]];
SELECT queueStage
FROM
spooledNormal, bannerOnly, decomposed, merged, tpSpooled, tpDecomposed, tpMerged =>
BEGIN
[] ← PrintQueue.Requeue[qOH: qOH, fromQueue: queueStage, toQueue: temp];
qOH.currentStatus ← canceledInQueue;
[] ← PrintQueue.Requeue[qOH: qOH, fromQueue: temp, toQueue: aborted];
QueueControl.WaitAbortQueueEmpty[];
END;
retransmit =>
BEGIN
[] ← PrintQueue.Requeue[qOH: qOH, fromQueue: queueStage, toQueue: temp];
qOH.currentStatus ← faxCanceled;
WITH q: qOH
SELECT
FROM
fax495 =>
FOR p:
CARDINAL
IN [0..q.phoneNoCount)
DO
q.transmitData[p].queuedForRetry ← FALSE;
ENDLOOP;
ENDCASE;
[] ← PrintQueue.Requeue[qOH: qOH, fromQueue: temp, toQueue: aborted];
QueueControl.WaitAbortQueueEmpty[];
END;
decomposing =>
BEGIN
state.internalControl.formatterEnabled ← FALSE;
DecomposerControl.Stop[status: canceledInDecomposer];
[] ← DecomposerControl.Stopped[wait];
QueueControl.WaitAbortQueueEmpty[];
state.internalControl.formatterEnabled ← TRUE;
IF state.clientControl.formatterEnabled THEN DecomposerControl.Start[];
END;
marking =>
BEGIN
state.internalControl.markerEnabled ← FALSE;
WITH q: qOH
SELECT
FROM
fax495 => markerProcs.stop[status: faxCanceled];
ENDCASE => markerProcs.stop[status: canceledInMarker];
[] ← markerProcs.stopped[wait];
QueueControl.WaitAbortQueueEmpty[];
state.internalControl.markerEnabled ← TRUE;
IF state.clientControl.markerEnabled THEN markerProcs.start[];
END;
merging =>
BEGIN
state.internalControl.markerEnabled ← FALSE;
MergeControl.Stop[status: canceledInMerger];
[] ← MergeControl.Stopped[wait];
QueueControl.WaitAbortQueueEmpty[];
state.internalControl.markerEnabled ← TRUE;
IF state.clientControl.markerEnabled THEN MergeControl.Start[];
END;
forwarding =>
BEGIN
state.internalControl.markerEnabled ← FALSE;
ForwardingControl.Stop[status: canceledInForwarder];
[] ← ForwardingControl.Stopped[wait];
QueueControl.WaitAbortQueueEmpty[];
state.internalControl.markerEnabled ← TRUE;
IF state.clientControl.markerEnabled THEN ForwardingControl.Start[];
END;
ENDCASE;
RETURN[DocumentStatusFromQObjStatus[qOH]];
END; --CancelDocument
****************************************
Print Service Control Operations:
****************************************
Start:
PUBLIC
PROCEDURE =
BEGIN
Called to undo Shutdown or Start PS after initialization.
IF currentCondition = stopped
THEN
BEGIN
currentCondition ← starting;
IF state.mode.current # repair
THEN
BEGIN
EnableQueuing[];
EnablePrinting[];
IF state.option = raven
THEN
--don't reference markerProcs if printing option = feps9700
WITH m: markerProcs
SELECT
FROM
raven => m.wakeupEngine[]; --Marker checks to be sure engine build is compatible.
ENDCASE;
state.mode.returnTo ← state.mode.current ← normal;
END
ELSE state.mode.returnTo ← normal;
NSPrintCourier.ExportRemoteProgram[];
Space.ForceOut[stateSpace];
currentCondition ← started;
END;
END; --StartPrintService
Stop:
PUBLIC
PROCEDURE =
BEGIN
Suspend and checkpoint all activities in anticipation of a power-off. PS will not be completely "stopped" if it is in repair mode.
IF currentCondition = started
THEN
BEGIN
currentCondition ← stopping;
IF state.mode.current # repair
THEN
BEGIN
DisableQueuing[];
DisablePrinting[];
IF state.option = raven
THEN
--don't reference markerProcs if printing option = feps9700
WITH m: markerProcs
SELECT
FROM
raven => m.dozeoffEngine[]; --Marker checks to be sure engine build is compatible.
ENDCASE;
state.mode.current ← state.mode.returnTo ← shutDown;
END
ELSE state.mode.returnTo ← shutDown;
NSPrintCourier.UnexportRemoteProgram[];
Space.ForceOut[stateSpace];
currentCondition ← stopped;
What else??
END;
END; --StopPrintService
StartPrinting:
PUBLIC
PROCEDURE [user: NSName.Name] =
BEGIN
IF state.clientControl.formatterEnabled
THEN
RETURN;
IF state.option = bansheeDl THEN
Call a proc which checks to see if any fonts need to be
rotated for banshee (raven fonts are rotated 90 degrees)
PSCommandInternal.RotateFonts90[];
IF
NOT fontsNoticed
THEN
BEGIN
DecomposerControl.NoticeNewFonts[
! DecomposerControl.DocumentInProgress =>
ERROR
Error[[documentInProgress[]]]];
fontsNoticed ← TRUE;
END;
IF
NOT testPatternsNoticed
THEN BEGIN
TestPattern.CatalogTPs[];
testPatternsNoticed ← TRUE;
END;
state.clientControl.formatterEnabled ← state.clientControl.markerEnabled ← TRUE;
IF state.internalControl.markerEnabled
THEN
BEGIN
DecomposerControl.Start[];
IF state.option = feps9700
THEN
BEGIN
MergeControl.Start[];
ForwardingControl.Start[];
END
ELSE
markerProcs.start[];
END;
state.lastUserToStartPrinting.length ← 0;
IF user.local.length > 0
THEN
state.lastUserToStartPrinting ← NSString.AppendString[
to: state.lastUserToStartPrinting, from: user.local
! NSString.StringBoundsFault => CONTINUE];
Space.ForceOut[stateSpace];
END; --StartPrinting
StopPrinting:
PUBLIC
PROCEDURE [user: NSName.Name, reason: NSString.String ← NSString.nullString] =
BEGIN
abortedCount: LONG CARDINAL ← state.docsAborted.total;
IF NOT state.clientControl.formatterEnabled THEN RETURN;
state.clientControl.formatterEnabled ← state.clientControl.markerEnabled ← FALSE;
IF state.internalControl.markerEnabled THEN StopPrintingInternal[];
state.lastUserToStopPrinting.length ← 0;
state.lastStopPrintingReason.length ← 0;
IF user.local.length > 0
THEN
state.lastUserToStopPrinting ← NSString.AppendString[
to: state.lastUserToStopPrinting, from: user.local
! NSString.StringBoundsFault => CONTINUE];
IF reason.length > 0
THEN
state.lastStopPrintingReason ← NSString.AppendString[
to: state.lastStopPrintingReason, from: reason
! NSString.StringBoundsFault => CONTINUE];
Space.ForceOut[stateSpace];
END; --StopPrinting
StartQueuing:
PUBLIC
PROCEDURE [user: NSName.Name] =
BEGIN
IF state.clientControl.spooler = enabled THEN RETURN;
state.clientControl.spooler ← enabled;
IF state.internalControl.spooler = enabled
THEN
SpoolControl.Start[];
state.lastUserToStartQueuing.length ← 0;
IF user.local.length > 0
THEN
state.lastUserToStartQueuing ← NSString.AppendString[
to: state.lastUserToStartQueuing, from: user.local
! NSString.StringBoundsFault => CONTINUE];
Space.ForceOut[stateSpace];
END; --StartQueuing
StopQueuing:
PUBLIC
PROCEDURE [user: NSName.Name, reason: NSString.String ← NSString.nullString] =
BEGIN
IF state.clientControl.spooler # enabled THEN RETURN;
state.clientControl.spooler ← disabled;
IF state.internalControl.spooler = enabled
THEN
BEGIN
SpoolControl.Stop[aborted];
[] ← SpoolControl.Stopped[wait];
END;
state.lastUserToStopQueuing.length ← 0;
state.lastStopQueuingReason.length ← 0;
IF user.local.length > 0
THEN
state.lastUserToStopQueuing ← NSString.AppendString[
to: state.lastUserToStopQueuing, from: user.local
! NSString.StringBoundsFault => CONTINUE];
IF reason.length > 0
THEN
state.lastStopQueuingReason ← NSString.AppendString[
to: state.lastStopQueuingReason, from: reason
! NSString.StringBoundsFault => CONTINUE];
Space.ForceOut[stateSpace];
END; --StopQueuing
ShutDownEngine:
PUBLIC
PROCEDURE =
BEGIN
WITH s: state
SELECT
FROM
raven =>
IF s.engineBuild > b1
THEN
WITH m: markerProcs
SELECT
FROM
raven => m.dozeoffEngine[];
ENDCASE => ERROR --Marker procs engine type disagrees with state record.
ELSE ERROR Error[[incompatiblePrintingOption[]]];
ENDCASE => ERROR Error[[incompatiblePrintingOption[]]];
END; --ShutdownEngine
WakeUpEngine:
PUBLIC
PROCEDURE =
BEGIN
WITH s: state
SELECT
FROM
raven =>
IF s.engineBuild > b1
THEN
WITH m: markerProcs
SELECT
FROM
raven => m.wakeupEngine[];
ENDCASE => ERROR --Marker procs engine type disagrees with state record.
ELSE ERROR Error[[incompatiblePrintingOption[]]];
ENDCASE => ERROR Error[[incompatiblePrintingOption[]]];
END; --WakeupEngine
PSCOMMANDINTERNAL PROCEDURES:--
EnablePrinting:
PUBLIC
PROCEDURE =
BEGIN
IF state.internalControl.formatterEnabled THEN RETURN;
state.internalControl.formatterEnabled ← state.internalControl.markerEnabled ← TRUE;
IF state.clientControl.markerEnabled
THEN
BEGIN
DecomposerControl.Start[];
IF state.option = feps9700
THEN
BEGIN
MergeControl.Start[];
ForwardingControl.Start[];
END
ELSE
markerProcs.start[];
END;
Space.ForceOut[stateSpace];
END; --EnablePrinting
DisablePrinting:
PUBLIC
PROCEDURE =
BEGIN
IF NOT state.internalControl.formatterEnabled THEN RETURN;
state.internalControl.formatterEnabled ← state.internalControl.markerEnabled ← FALSE;
IF state.clientControl.markerEnabled THEN StopPrintingInternal[];
Space.ForceOut[stateSpace];
END; --DisablePrinting
EnableQueuing:
PUBLIC
PROCEDURE =
BEGIN
IF state.internalControl.spooler = enabled THEN RETURN;
state.internalControl.spooler ← enabled;
IF state.clientControl.spooler = enabled THEN SpoolControl.Start[];
Space.ForceOut[stateSpace];
END; --EnableQueuing
DisableQueuing:
PUBLIC
PROCEDURE [reason: PSState.SpoolerState ← disabled] =
BEGIN
IF state.internalControl.spooler # enabled THEN RETURN;
state.internalControl.spooler ← reason;
IF state.clientControl.spooler = enabled
THEN
BEGIN
IF reason = disabledForMarking THEN SpoolControl.Suspend[] ELSE SpoolControl.Stop[aborted];
[] ← SpoolControl.Stopped[wait];
END;
Space.ForceOut[stateSpace];
END; --DisableQueuing
PRIVATE PROCEDURES:--
Procedures used by ENQUEUE:--
AbortAndDeleteSourceStream:
PROCEDURE [stream: NSDataStream.SourceStream] =
BEGIN
NSDataStream.Abort[stream];
Stream.Delete[stream ! NSDataStream.Aborted => CONTINUE];
END; --AbortAndDeleteSourceStream
CompleteEnqueue:
PROCEDURE [qOH: PrintQueue.QueueObjectHandle, file: NSFile.Handle,
beginSpoolDate: BasicTime.GMT] = BEGIN
--This procedure does a few final things with the qOH before putting it on the spooled queue. It is forked by Enqueue so that Enqueue's client is not kept hanging any longer than necessary.--
selection: NSFile.Selections ← NSFile.noSelections;
attribute: NSFile.Attributes ← NSFile.GetAttributesRecord[];
IF state.spoolerTrace # none THEN DisplayInitialSpoolInfo[qOH];
Get true file size...
selection.interpreted[dataSize] ← TRUE;
NSFile.GetAttributes[file, selection, attribute, session];
qOH.fileSize ← attribute.dataSize;
NSFile.Close[file, session];
NSFile.ReleaseAttributesRecord[attribute];
qOH.fileQueuedDate ← BasicTime.Update[];
qOH.currentStatus ← spooled;
[] ← PrintQueue.Requeue[qOH: qOH, fromQueue: spooling, toQueue: spooledNormal];
IF state.spoolerTrace = verbose THEN DisplayFinalSpoolInfo[qOH, beginSpoolDate];
If printing option is a B2 raven engine, wake up the engine if necessary...
IF state.option = raven
THEN
WITH m: markerProcs
SELECT
FROM
raven =>
WITH d: m.status[].engine
SELECT
FROM
raven =>
IF d.raven
IN [aboutToDozeOff..fuserUnderTemperature]
THEN
m.wakeupEngine[];
ENDCASE => ERROR;
ENDCASE => ERROR;
END; -- of CompleteEnqueue
CopyDocParametersToQueueObject:
PROCEDURE [qOH: PrintQueue.QueueObjectHandle,
parms: PSCommand.DocumentParameters] = BEGIN
timeLength: CARDINAL = 18;
timeString: LONG STRING ← [timeLength];
qOH.fileName.length ← 0;
qOH.localFileName.length ← 0;
IF parms.name # NSString.nullString
THEN
BEGIN
PrintQueue.CopyStringIn[qOH, parms.name, fileName];
PrintQueue.CopyStringIn[qOH, parms.name, localFileName];
END;
Append time to local file name (if there was no file name the date will serve as one)...
Time.AppendCurrent[timeString];
qOH.localFileName ← NSString.AppendString[qOH.localFileName, Str[timeString]
! NSString.StringBoundsFault => CONTINUE];
qOH.fileCreateDate ← parms.createDate;
IF parms.senderName # NSString.nullString
THEN
PrintQueue.CopyStringIn[qOH, parms.senderName, sender];
qOH.fileSize ← parms.size;
IF parms.recipientName # NSString.nullString
THEN
PrintQueue.CopyStringIn[qOH, parms.recipientName, recipient];
IF parms.message # NSString.nullString
THEN
PrintQueue.CopyStringIn[qOH, parms.message, operatorMsg];
qOH.numberCopies ← parms.copyCount;
--This is a kludge where we check for page number zero which is not allowed. (It is documented in Printing Protocol standard that page numbers start at 1.) The decomposer will act strangely if you give it page number zero. Since OS 5.0 Star used to send first PageToPrint=0, we need to have the kludge in for a while for backward compatibility. An AR has been submitted against Viewpoint and is expected to be fixed.
NOTE: This kludge should be taken out in some subsequent release.--
IF parms.firstPageToPrint = 0
OR parms.lastPageToPrint = 0
THEN
BEGIN
Invalid page numbers, so use default values
qOH.firstPageToPrint ← 1;
qOH.lastPageToPrint ← LAST[CARDINAL];
END ELSE BEGIN
qOH.firstPageToPrint ← parms.firstPageToPrint;
qOH.lastPageToPrint ← parms.lastPageToPrint;
END;
qOH.paper ← parms.paper;
qOH.staple ← parms.staple;
qOH.twoSided ← parms.twoSided;
qOH.priority ← LOOPHOLE[parms.priority];
qOH.releaseKey ← parms.releaseKey;
WITH s: state
SELECT
FROM
bansheeDl =>
BEGIN
dStatus: MarkerControl.EngineSpecific ← markerProcs.status[].engine;
WITH d: dStatus
SELECT
FROM
bansheeDl =>
BEGIN
IF parms.paper = PaperTypesExtras.nullPaper THEN qOH.paper ← d.paper; --Default to currently loaded paper size if size not specified
IF qOH.paper # d.paper
THEN
PSCommand.Error[[enqueue[mediumUnavailable]]];
END;
ENDCASE => ERROR;
END;
d1 =>
BEGIN
dStatus: MarkerControl.EngineSpecific ← markerProcs.status[].engine;
WITH d: dStatus
SELECT
FROM
d1 =>
BEGIN
IF parms.paper = PaperTypesExtras.nullPaper THEN qOH.paper.knownSize ← d.paperSize; --Default to currently loaded paper size if size not specified
IF qOH.paper.knownSize # d.paperSize
THEN
PSCommand.Error[[enqueue[mediumUnavailable]]];
END;
ENDCASE => ERROR;
END;
fax295 =>
BEGIN
SELECT s.paperWidth
FROM
PaperTypes.PaperMMDimension[letter].short =>
BEGIN
--Paper width is for letter/legal paper.
IF parms.paper = PaperTypesExtras.nullPaper THEN qOH.paper.knownSize ← letter; --Default to letter if size not specified
IF qOH.paper.knownSize = a4 THEN qOH.paper.knownSize ← legal; --Allow a4 documents to be printed on legal paper
IF qOH.paper.knownSize # letter
AND qOH.paper.knownSize # legal
THEN
PSCommand.Error[[enqueue[mediumUnavailable]]];
END;
PaperTypes.PaperMMDimension[a4].short =>
BEGIN
--Paper width is for a4 paper.
IF parms.paper = PaperTypesExtras.nullPaper THEN qOH.paper.knownSize ← a4; --Default to a4 if size not specified
IF qOH.paper.knownSize # a4 THEN PSCommand.Error[[enqueue[mediumUnavailable]]];
END;
ENDCASE => ERROR; --Paper width is other than letter/legal or a4???
END;
fax495 =>
BEGIN
SELECT s.paperWidth
FROM
PaperTypes.PaperMMDimension[letter].short =>
BEGIN
--Paper width is for letter/legal paper.
IF parms.paper = PaperTypesExtras.nullPaper THEN qOH.paper.knownSize ← letter; --Default to letter if size not specified
IF qOH.paper.knownSize = a4 THEN qOH.paper.knownSize ← legal; --Allow a4 documents to be printed on legal paper
IF qOH.paper.knownSize # letter
AND qOH.paper.knownSize # legal
THEN
PSCommand.Error[[enqueue[mediumUnavailable]]];
END;
PaperTypes.PaperMMDimension[a4].short =>
BEGIN
--Paper width is for a4 paper.
IF parms.paper = PaperTypesExtras.nullPaper THEN qOH.paper.knownSize ← a4; --Default to a4 if size not specified
IF qOH.paper.knownSize # a4 THEN PSCommand.Error[[enqueue[mediumUnavailable]]];
END;
ENDCASE => ERROR; --Paper width is other than letter/legal or a4???
IF parms.message # NSString.nullString THEN GetFaxDataFromString[parms.message, qOH]
ELSE
--If no message, do a local print.
WITH q: qOH
SELECT
FROM
fax495 => q.localPrintStatus ← queued;
ENDCASE => ERROR;
END;
feps9700 =>
BEGIN
IF parms.paper = PaperTypesExtras.nullPaper
THEN qOH.paper.knownSize ←
IF s.paperSupply.size1 # letter AND s.paperSupply.size2 # letter
THEN s.paperSupply.size1 ELSE letter;
IF qOH.paper.knownSize # s.paperSupply.size1
AND
qOH.paper.knownSize # s.paperSupply.size2
THEN
PSCommand.Error[[enqueue[mediumUnavailable]]];
END;
fx3500 =>
BEGIN
dStatus: MarkerControl.EngineSpecific ← markerProcs.status[].engine;
WITH d: dStatus
SELECT
FROM
fx3500 =>
BEGIN
IF parms.paper = PaperTypesExtras.nullPaper
THEN qOH.paper.knownSize ←
IF d.paperSupply.size1 # a4 AND d.paperSupply.size2 # a4
THEN d.paperSupply.size1 ELSE a4;
IF qOH.paper.knownSize # d.paperSupply.size1
AND
qOH.paper.knownSize # d.paperSupply.size2 THEN
PSCommand.Error[[enqueue[mediumUnavailable]]];
END;
ENDCASE => ERROR;
END;
raven =>
BEGIN
IF parms.paper = PaperTypesExtras.nullPaper
THEN qOH.paper.knownSize ←
IF s.paperSupply.size1 # letter AND s.paperSupply.size2 # letter
THEN s.paperSupply.size1 ELSE letter;
IF qOH.paper.knownSize # s.paperSupply.size1
AND
qOH.paper.knownSize # s.paperSupply.size2
THEN
PSCommand.Error[[enqueue[mediumUnavailable]]];
END;
ENDCASE => ERROR; --unknown printing option?
END; --CopyDocParametersToQueueObject
ConvertSpoolControlError:
PROCEDURE [sType: SpoolControl.ErrorTypes]
RETURNS [error: PSCommand.ErrorRecord] =
BEGIN
RETURN [
SELECT sType
FROM
busy => [enqueue[busySpooling]],
spoolingDisabled => [enqueue[spoolingDisabled]],
tooManyConnections => [enqueue[tooManyClients]],
spoolFull => [enqueue[spoolingQueueFull]],
ENDCASE => ERROR]
END; --ConvertSpoolControlError
CreateSpoolFile:
PROCEDURE [docParameters: PSCommand.DocumentParameters]
RETURNS [file: NSFile.Handle ← NSFile.nullHandle,
qOH: PrintQueue.QueueObjectHandle ← PrintQueue.nilQueueObjectHandle] = BEGIN
createFileError: PSCommand.ErrorRecord; BEGIN
fileBytes: LONG CARDINAL;
qOH ← PrintQueue.Requeue[fromQueue: inactive, toQueue: spooling];
qOH.currentStatus ← PrintQueue.ObjectStatus[spooling];
CopyDocParametersToQueueObject[qOH, docParameters
! PSCommand.Error => {
IF state.spoolerTrace # none THEN PSAsyncMsg.PutMesaString[" **PSCommand.Error[[enqueue[mediumUnavailable]]]"L];
qOH.currentStatus ← PrintQueue.ObjectStatus[spoolFailure];
[] ← PrintQueue.Requeue[qOH: qOH, fromQueue: spooling,
toQueue: aborted];
REJECT}];
fileBytes ← IF qOH.fileSize = 0 THEN 20 ELSE qOH.fileSize;
[qOH.fileID, file] ← QueueFile.CreateTempFile[qOH.localFileName, fileBytes !
QueueFile.CreateError => {createFileError ← [enqueue[other]]; GOTO Error};
QueueFile.InsufficientPages =>
{createFileError ← [insufficientSpace[]]; GOTO Error};];
qOH.uid ← BasicTime.GetUniversalID[];
EXITS
Error =>
BEGIN
qOH.currentStatus ← PrintQueue.ObjectStatus[spoolFailure];
[] ← PrintQueue.Requeue[qOH: qOH,
fromQueue: spooling, toQueue: aborted];
PSCommand.Error[createFileError];
END;
END;
END; --CreateSpoolFile
GetFaxDataFromString:
PROCEDURE [
string: NSString.String, qOH: PrintQueue.QueueObjectHandle] = BEGIN
WITH q: qOH
SELECT
FROM
fax495 =>
BEGIN
endOfParse: BOOLEAN ← FALSE;
startParseIndex, --index of string char where parsing should begin
stopParseIndex, --index of string char where parsing should end (past last legal char)
actualLength, --actual number of legal phone number chars found for a given phone number
parseIndex, --current string char being looked at during parse
phoneNos, --number of phone numbers found
phoneNoIndex
--index into queue object phone number array where next phone number goes
: CARDINAL ← 0;
chset: PrincOps.BYTE ← 0;
char: NSString.Character;
msgLength: CARDINAL ← string.length;
chsetChangeMarker: PrincOps.BYTE = 377B;
delimiter: NSString.Character = [0, 57B]; --slash char '/
blank: NSString.Character = [0, 40B];
comma: NSString.Character = [0, 54B];
letterL: NSString.Character = [0, 114B];
minActualLength: CARDINAL = 2; --min # of actual phone number chars allowed
maxActualLength: CARDINAL = 27; --max # of actual phone number chars allowed
EndOfParse: SIGNAL = CODE;
ParseError:
ERROR =
CODE;
ActualPhoneNoChar:
PROC [c: NSString.Character]
RETURNS [
BOOLEAN] =
BEGIN
SELECT c
FROM
[0, 60B]--0--, [0, 61B]--1--, [0, 62B]--2--, [0, 63B]--3--,
[0, 64B]--4--, [0, 65B]--5--, [0, 66B]--6--, [0, 67B]--7--,
[0, 70B]--8--, [0, 71B]--9--, [0, 120B]--P--,
[0, 52B]
--*--, [0, 43B]
--#-- =>
RETURN [
TRUE];
ENDCASE => RETURN [FALSE];
END; --ActualPhoneNoChar
GetNextChar:
PROCEDURE
RETURNS [NSString.Character] =
BEGIN
code: PrincOps.BYTE;
ValidCharacter:
PROC [c: NSString.Character]
RETURNS [
BOOLEAN] =
BEGIN
SELECT c
FROM
[0, 60B]--0--, [0, 61B]--1--, [0, 62B]--2--, [0, 63B]--3--,
[0, 64B]--4--, [0, 65B]--5--, [0, 66B]--6--, [0, 67B]--7--,
[0, 70B]--8--, [0, 71B]--9--, [0, 55B]--minus--,
[0, 50B]--leftParen--, [0, 51B]--rightParen--,
[0, 120B]--P--, [0, 52B]--*--, [0, 43B]--#--,
[41B, 76B]--hyphen--, blank, comma, letterL => RETURN [TRUE];
ENDCASE => RETURN [FALSE];
END; --ValidCharacter
IF parseIndex >= stopParseIndex THEN SIGNAL EndOfParse;
code ← string.bytes[parseIndex];
IF code = chsetChangeMarker
THEN
BEGIN
IF (parseIndex ← parseIndex + 1) >= msgLength THEN ERROR ParseError;
chset ← string.bytes[parseIndex];
IF (parseIndex ← parseIndex + 1) >= msgLength THEN ERROR ParseError;
code ← string.bytes[parseIndex];
END;
parseIndex ← parseIndex + 1;
IF NOT ValidCharacter[[chset, code]] THEN ERROR ParseError;
RETURN[[chset, code]];
END; --GetNextChar
LookForSinglePhoneNo:
PROCEDURE =
BEGIN
chset ← parseIndex ← 0;
stopParseIndex ← msgLength;
q.localPrintStatus ← null;
q.phoneNoCount ← 1;
q.transmitData ← ALL[];
q.transmitData[0].status ← queued;
q.transmitData[0].phoneNumber ← [
bytes: LOOPHOLE[@q.transmitData[0].phoneNumberBody],
length: 0, maxlength: PrintQueue.maxPhoneNoLength];
actualLength ← 0;
char ← GetNextChar[!
EndOfParse, ParseError => GOTO localPrint];
UNTIL char = comma
OR char = letterL
--letter L no allowed in phone number
OR q.transmitData[0].phoneNumber.length >= q.transmitData[0].phoneNumber.maxlength DO
q.transmitData[0].phoneNumber ←
NSString.AppendCharacter[q.transmitData[0].phoneNumber, char];
IF ActualPhoneNoChar[char] THEN actualLength ← actualLength + 1;
char ← GetNextChar[! EndOfParse =>
IF actualLength < minActualLength
OR actualLength > maxActualLength
THEN
GOTO localPrint ELSE GOTO finished;
ParseError => GOTO localPrint];
ENDLOOP;
IF actualLength < minActualLength
OR actualLength > maxActualLength
THEN
GOTO localPrint;
DO
IF char # blank THEN GOTO localPrint;
char ← GetNextChar[! EndOfParse =>
GOTO finished;
ParseError => GOTO localPrint];
ENDLOOP;
EXITS
finished => NULL;
localPrint =>
BEGIN
q.localPrintStatus ← queued;
q.phoneNoCount ← 0;
q.transmitData ← ALL[];
END;
END; --LookForSinglePhoneNo
BEGIN
IF msgLength = 0 THEN {q.localPrintStatus ← queued; GOTO done};
parseIndex ← NSString.ScanForCharacter[delimiter, string];
IF parseIndex =
LAST[
CARDINAL]
THEN
--no slash found
GOTO lookForSinglePhoneNo;
IF
NOT NSString.EqualCharacter[delimiter, string, parseIndex + 1]
THEN
--second slash not found
GOTO lookForSinglePhoneNo;
startParseIndex ← parseIndex + 2;
parseIndex ← NSString.ScanForCharacter[delimiter, string, startParseIndex];
IF parseIndex =
LAST[
CARDINAL]
THEN
--no slash found
GOTO lookForSinglePhoneNo;
IF
NOT NSString.EqualCharacter[delimiter, string, parseIndex + 1]
THEN
--second slash not found
GOTO lookForSinglePhoneNo;
stopParseIndex ← parseIndex;
parseIndex ← startParseIndex;
DO
--Look for leading blanks or commas and letter L for local print.
char ← GetNextChar[! EndOfParse, ParseError => GOTO lookForSinglePhoneNo];
SELECT char
FROM
letterL =>
BEGIN
q.localPrintStatus ← queued;
Look for comma after L:
char ← GetNextChar[! EndOfParse =>
GOTO done;
ParseError => GOTO lookForSinglePhoneNo];
UNTIL char = comma
DO
IF char # blank THEN GOTO lookForSinglePhoneNo;
char ← GetNextChar[! EndOfParse =>
GOTO done;
ParseError => GOTO lookForSinglePhoneNo];
ENDLOOP;
EXIT;
END;
blank, comma => LOOP;
ENDCASE => EXIT;
ENDLOOP;
DO
--Look for phone numbers.
Extra blanks and commas allowed between items:
UNTIL char # blank
AND char # comma
DO
char ← GetNextChar[! EndOfParse =>
IF q.localPrintStatus = queued
OR q.phoneNoCount > 0
THEN
GOTO done
ELSE GOTO lookForSinglePhoneNo;
ParseError => GOTO lookForSinglePhoneNo];
ENDLOOP;
phoneNos ← phoneNos + 1;
actualLength ← 0;
Look for a phone number before next comma:
UNTIL char = comma
OR char = letterL
--letter L is valid only as local print indicator at beginning of string.
OR q.transmitData[phoneNoIndex].phoneNumber.length >= q.transmitData[phoneNoIndex].phoneNumber.maxlength DO
q.transmitData[phoneNoIndex].phoneNumber ←
NSString.AppendCharacter[q.transmitData[phoneNoIndex].phoneNumber, char];
IF ActualPhoneNoChar[char] THEN actualLength ← actualLength + 1;
char ← GetNextChar[! EndOfParse =>
IF actualLength < minActualLength
OR actualLength > maxActualLength
THEN
GOTO lookForSinglePhoneNo ELSE GOTO done;
ParseError => GOTO lookForSinglePhoneNo];
ENDLOOP;
phoneNoIndex ← phoneNoIndex + 1;
IF actualLength < minActualLength
OR actualLength > maxActualLength
THEN
GOTO lookForSinglePhoneNo;
IF phoneNos >= PrintQueue.maxFaxPhoneNos THEN GOTO done;
UNTIL char = comma
DO
--Char should be a comma (or a blank before comma) or else phone number to too long
IF char # blank THEN GOTO lookForSinglePhoneNo; --Phone number was too long or an L was found.
char ← GetNextChar[! EndOfParse =>
GOTO done;
ParseError => GOTO lookForSinglePhoneNo];
ENDLOOP;
ENDLOOP;
EXITS
done =>
IF phoneNos > 0
THEN
BEGIN
FOR i:
CARDINAL
IN [0..phoneNos)
DO
q.transmitData[i].status ← queued;
ENDLOOP;
q.phoneNoCount ← phoneNos;
END;
lookForSinglePhoneNo => LookForSinglePhoneNo[];
END;
END;
ENDCASE;
END; --GetFaxDataFromString
Debugging procedures
DisplayInitialSpoolInfo:
PROCEDURE [qOH: PrintQueue.QueueObjectHandle] =
BEGIN
nsPrintRequest: NSString.String = Str["--Print Request by <1>"L];
nsFile: NSString.String = Str["--File: <1>"L];
PSAsyncMsg.Expand1AndPutString[nsPrintRequest, qOH.sender];
PSAsyncMsg.Expand1AndPutString[nsFile, qOH.fileName];
END; -- DisplayInitialSpoolInfo
DisplayFinalSpoolInfo:
PROCEDURE [qOH: PrintQueue.QueueObjectHandle,
beginSpoolDate: BasicTime.GMT] = BEGIN
nsComplete: NSString.String = Str["--File transfer took <1> seconds; completed: <2>"];
nsCopiesAndLength: NSString.String = Str["--Copies: <1>; BYTE Length: <2>"L];
stringArray: ARRAY [0..2) OF NSString.String;
spoolTime: LONG CARDINAL ← BasicTime.SecondsSinceEpoch[qOH.fileQueuedDate] - BasicTime.SecondsSinceEpoch[beginSpoolDate];
sTime: LONG STRING ← [10];
sDate: LONG STRING ← [20];
sCopies: LONG STRING ← [10];
sLength: LONG STRING ← [15];
String.AppendLongDecimal[sTime, spoolTime];
stringArray[0] ← Str[sTime];
Time.Append[sDate, Time.Unpack[qOH.fileQueuedDate]];
stringArray[1] ← Str[sDate];
PSAsyncMsg.ExpandArrayAndPutString[nsComplete, DESCRIPTOR[stringArray]];
String.AppendDecimal[sCopies, qOH.numberCopies];
String.AppendLongDecimal[sLength, qOH.fileSize];
stringArray[0] ← Str[sCopies];
stringArray[1] ← Str[sLength];
PSAsyncMsg.ExpandArrayAndPutString[nsCopiesAndLength, DESCRIPTOR[stringArray]];
END; -- DisplayFinalSpoolInfo
*********************************--
Procedures used by LISTDOCUMENTS:--
DocumentStatusFromQObjStatus:
PROCEDURE [qOH: PrintQueue.QueueObjectHandle]
RETURNS [PSCommand.DocumentStatus] = BEGIN
RETURN[
SELECT qOH.currentStatus
FROM
restart => [pending[restart]],
spooling => [pending[spooling]],
spooled => [pending[spooled]],
decomposing => [inProgress[decomposing]],
decomposed => [inProgress[decomposed]],
marking => [inProgress[marking]],
printed => [completed[printed]],
merging => [inProgress[merging]],
merged => [inProgress[merged]],
forwarding => [inProgress[forwarding]],
forwarded => [completed[forwarded]],
canceledInDecomposer => [canceled[canceledInDecomposer]],
canceledInMarker => [canceled[canceledInMarker]],
canceledInMerger => [canceled[canceledInMerger]],
canceledInForwarder => [canceled[canceledInForwarder]],
canceledInQueue => [canceled[canceledInQueue]],
spoolFailure => [rejected[spoolFailure]],
decomposeFailure => [aborted[decomposeFailure]],
markFailure => [aborted[markFailure]],
mergeFailure => [aborted[mergeFailure]],
forwardFailure => [aborted[forwardFailure]],
sysRestartInSpooler => [aborted[sysRestartInSpooler]],
sysRestartInDecomposer => [aborted[sysRestartInDecomposer]],
sysRestartInMarker => [aborted[sysRestartInMarker]],
sysRestartInMerger => [aborted[sysRestartInMerger]],
sysRestartInForwarder => [aborted[sysRestartInForwarder]],
sysRestartInQueue => [aborted[sysRestartInQueue]],
faxInProgress => [inProgress[faxStatus]],
faxCompleted => [completed[faxStatus]],
faxCanceled => [canceled[faxStatus]],
faxAborted => [aborted[faxStatus]],
ENDCASE => [unknown[]]];
END; --DocumentStatusFromQObjStatus
IDFilterOk:
PROCEDURE [filterID, qObjID: PSCommand.DocumentID]
RETURNS [BOOLEAN] = BEGIN
An id gets through the id filter if the id filter is nil or the id matches the id filter exacly.
IF filterID = PSCommand.nullDocumentID THEN RETURN[TRUE]
ELSE
BEGIN
IF filterID = qObjID THEN RETURN[TRUE]
ELSE RETURN[FALSE];
END;
END; --IDFilterOk
ListQueueStage:
PROCEDURE [
queueStage: PrintQueue.QueueStage, proc: PSCommand.DocumentProc,
filter: QueueObjectFilter, scratchQOH: PrintQueue.QueueObjectHandle,
scratchDocAttributes: PSCommand.DocumentAttributes,
scratchFaxMitData: LONG DESCRIPTOR FOR ARRAY OF PSCommand.FaxTransmitData]
RETURNS [continue: BOOLEAN ← TRUE] = BEGIN
ListQueueStage goes through the documents (referenced by their queue object handle) in the specified queue stage and lists those documents specified by the other elements of the filter: id, file name and sender.
qOH, nextQOH: PrintQueue.QueueObjectHandle;
CopyDocumentAttributes: PROCEDURE = BEGIN
Copies the queue object of the desired document and then copies the attributes from the queue object to the attribute record.
PrintQueue.CopyQueueObject[fromQOH: qOH, toQOH: scratchQOH];
SELECT scratchQOH.option
FROM
bansheeDl => scratchDocAttributes^ ← [optionDependent: bansheeDl[]];
d1 => scratchDocAttributes^ ← [optionDependent: d1[]];
fax295 => scratchDocAttributes^ ← [optionDependent: fax295[]];
fax495 => scratchDocAttributes^ ← [optionDependent: fax495[]];
feps9700 => scratchDocAttributes^ ← [optionDependent: feps9700[]];
fx3500 => scratchDocAttributes^ ← [optionDependent: fx3500[]];
raven => scratchDocAttributes^ ← [optionDependent: raven[]];
ENDCASE => ERROR;
scratchDocAttributes.id ← scratchQOH.uid;
scratchDocAttributes.name ← scratchQOH.fileName;
scratchDocAttributes.sender ← scratchQOH.sender;
scratchDocAttributes.recipient ← scratchQOH.recipient;
scratchDocAttributes.errorMessage ← scratchQOH.errorMsg;
scratchDocAttributes.status ← DocumentStatusFromQObjStatus[scratchQOH];
scratchDocAttributes.priority ← LOOPHOLE[scratchQOH.priority]; --PrintQueue.Priority = NSPrint.PriorityHint
scratchDocAttributes.sourceSystemElement ← scratchQOH.sourceSystemElement;
scratchDocAttributes.sizeInBytes ← scratchQOH.fileSize;
scratchDocAttributes.pagesDecomposed ← scratchQOH.platesDecomposed;
scratchDocAttributes.numberOfCopies ← scratchQOH.numberCopies;
scratchDocAttributes.dateReceived ← scratchQOH.fileCreateDate;
scratchDocAttributes.secondsInFormatter ← scratchQOH.decomposeTime;
scratchDocAttributes.completionDate ← scratchQOH.completionDate;
WITH q: scratchQOH
SELECT
FROM
fax495 =>
--Copy fax specific data.
WITH d: scratchDocAttributes
SELECT
FROM
fax495 =>
BEGIN
OPEN d.faxStatus;
localPrint ← LOOPHOLE[q.localPrintStatus];
localPrintCompletionDate ← q.localPrintCompletionDate;
phoneNumberCount ← q.phoneNoCount;
FOR i:
CARDINAL
IN [0..q.phoneNoCount)
DO
scratchFaxMitData[i].phoneNumber ← q.transmitData[i].phoneNumber;
scratchFaxMitData[i].transmit ← LOOPHOLE[q.transmitData[i].status];
scratchFaxMitData[i].retryCount ← q.transmitData[i].retryCount;
scratchFaxMitData[i].willRetry ← q.transmitData[i].queuedForRetry;
scratchFaxMitData[i].completionDate ← q.transmitData[i].completionDate;
scratchFaxMitData[i].phoneCallElapsedTime ← q.transmitData[i].elapsedTime;
scratchFaxMitData[i].errorCode ← q.transmitData[i].errorCode;
ENDLOOP;
transmitData ← DESCRIPTOR[BASE[scratchFaxMitData], q.phoneNoCount];
END;
ENDCASE => ERROR; --Printing option types types disagree
ENDCASE;
END; --CopyDocumentAttributes
qOH ← PrintQueue.Previous[fromQueue: queueStage]; --get last (i.e. newest) document from queue stage
Go through all the documents in the queue stage:
UNTIL qOH = PrintQueue.nilQueueObjectHandle DO
nextQOH ← PrintQueue.Previous[qOH: qOH, fromQueue: queueStage];
--get next older doc from queue stage
Next queue object is gotten here, because after the client proc is called we don't know if the original queue object will even be on the queue stage we are listing.
IF filter.status[qOH.currentStatus]
--If the document has an acceptable queue object status--
THEN
IF StringFilterOk[filter.sender, qOH.sender]
THEN
IF StringFilterOk[filter.name, qOH.fileName]
THEN
IF IDFilterOk[filter.id, qOH.uid] THEN BEGIN
If the other filters are either nil or match
exactly then list the document.
CopyDocumentAttributes[];
continue ← proc[scratchDocAttributes];
IF NOT continue THEN RETURN;
END;
qOH ← nextQOH;
ENDLOOP;
END; --ListQueueStage
QObjFilterFromClientFilter:
PROCEDURE [clientFilter:
LONG
POINTER
TO PSCommand.DocumentFilter, qObjFilter:
LONG
POINTER
TO QueueObjectFilter] =
BEGIN
qObjFilter.id ← clientFilter.id;
qObjFilter.name ← clientFilter.name;
qObjFilter.sender ← clientFilter.sender;
qObjFilter.status ← ALL[FALSE];
FOR s: PSCommand.SimpleDocStatus
IN PSCommand.SimpleDocStatus
DO
IF clientFilter.status[s]
THEN SELECT s
FROM
pending =>
qObjFilter.status[restart] ← qObjFilter.status[spooling] ←
qObjFilter.status[spooled] ← TRUE;
inProgress =>
qObjFilter.status[decomposing] ← qObjFilter.status[decomposed] ←
qObjFilter.status[marking] ← qObjFilter.status[merging] ←
qObjFilter.status[merged] ← qObjFilter.status[forwarding] ←
qObjFilter.status[faxInProgress] ← TRUE;
completed =>
qObjFilter.status[printed] ← qObjFilter.status[forwarded] ←
qObjFilter.status[faxCompleted] ← TRUE;
completedWithWarnings => NULL;
unknown => NULL;
rejected => qObjFilter.status[spoolFailure] ← TRUE;
aborted =>
qObjFilter.status[decomposeFailure] ←
qObjFilter.status[markFailure] ←
qObjFilter.status[mergeFailure] ←
qObjFilter.status[forwardFailure] ←
qObjFilter.status[sysRestartInSpooler] ←
qObjFilter.status[sysRestartInDecomposer] ←
qObjFilter.status[sysRestartInMarker] ←
qObjFilter.status[sysRestartInMerger] ←
qObjFilter.status[sysRestartInForwarder] ←
qObjFilter.status[sysRestartInQueue] ←
qObjFilter.status[faxAborted] ← TRUE;
canceled =>
qObjFilter.status[canceledInQueue] ←
qObjFilter.status[canceledInDecomposer] ←
qObjFilter.status[canceledInMarker] ←
qObjFilter.status[canceledInMerger] ←
qObjFilter.status[canceledInForwarder] ←
qObjFilter.status[faxCanceled] ← TRUE;
held => NULL;
ENDCASE;
ENDLOOP;
END; --QObjFilterFromClientFilter
StringFilterOk:
PROCEDURE [filterString, qObjString: NSString.String]
RETURNS [BOOLEAN] = BEGIN
A string gets through the string filter if the string filter is nil or the string matches the string filter exactly.
IF filterString = nsNil THEN RETURN[TRUE]
ELSE RETURN[NSString.EquivalentStrings[filterString, qObjString]];
END; --StringFilterOk
*********************************--
Procedures used by CONTROL PROCEDURES:--
RequeueDecomposedDocs:
PROCEDURE [fromQueue: PrintQueue.QueueStage] =
BEGIN
qOH: PrintQueue.QueueObjectHandle ← PrintQueue.Requeue[
fromQueue: fromQueue, toQueue: spooledNormal, position: front];
UNTIL qOH = PrintQueue.nilQueueObjectHandle
DO
IF qOH.printObjectHandle #
NIL
THEN
DecomposerControl.FreeDecomposeObject[qOH.uid];
qOH.printObjectHandle ← NIL;
qOH.currentStatus ← restart;
qOH ← PrintQueue.Requeue[
fromQueue: fromQueue, toQueue: spooledNormal, position: front];
ENDLOOP;
END; --RequeueDecomposedDocs
StopPrintingInternal:
PROCEDURE =
BEGIN
--retry all docs in progress
QUESTION: Why do we free decompose handles of decomposed documents?
ANSWER: For feps9700, at least we MUST requeue decomposed documents or else we end up with documents in the queue with the status "Being formatted" when printing is stopped!
IF state.option = feps9700
THEN
BEGIN
ForwardingControl.Stop[status: merged];
MergeControl.Stop[status: restart];
END
ELSE
markerProcs.stop[status: restart];
DecomposerControl.Stop[status: restart];
RequeueDecomposedDocs[fromQueue: retransmit];
RequeueDecomposedDocs[fromQueue: decomposed];
[] ← DecomposerControl.Stopped[wait];
IF state.option = feps9700
THEN
BEGIN
[] ← ForwardingControl.Stopped[wait];
[] ← MergeControl.Stopped[wait];
END
ELSE
[] ← markerProcs.stopped[wait];
END; --StopPrintingInternal
Str: PROCEDURE [s: LONG STRING] RETURNS [ns: NSString.String] = INLINE BEGIN
RETURN[NSString.StringFromMesaString[s]]
END. --PSCommandAImpl
LOG when/who/what
****EARLIER LOG ENTRIES DELETED. See archived version from 8.0.
6-Sep-84 12:58:10 - Jacks - Updated to 9.0 PS interfaces; removed code for aps5; added code for banshee, fax295 and feps9700.
20-Sep-84 13:49:31 - Jacks - Moved the waking up of a dozing raven to Enqueue from DecomposerControlImpl proc.
26-Oct-84 15:03:04 - Jacks - Added code for feps9700.
15-Jan-85 15:25:13 - Jacks - Now save staple and twoSided options when present in NSPrint call (CopyPrintOptionsToQueueObject).
18-Jan-85 14:52:40 - Jacks - In StopPrintingInternal: now stop the decomposer before requeuing decomposed docs which eliminates a timing window which allowed an occasional document to end up on the decomposed queue when printing was stopped.
28-Feb-85 10:09:23 - Jacks - Now call RotateFonts90 every time in StartPrinting if the engine is bansheeDl to check if any fonts need to be rotated.
12-Mar-85 11:20:02 - Jacks - Put call to GetFaxDataFromString into CopyDocParametersToQueueObject.
15-Aug-85 16:46:48 - Jacks - Put in kludge for firstPageToPrint or lastPageToPrint = 0.
10-Sep-85 15:04:12 - Jacks - Got queueObject, documentAttrRecord and faxMitData out of local frame in ListQueueStage; ListDocuments temporarily exported by PSCommandExtras; default d1 and banshee paper size to what is currently loaded.
24-Sep-85 14:04:34 - Jacks - Put PSCommandExtras stuff into PSCommand.
11-Jun-86 14:03:22 - Jacks - Again fixed space leak in ListDocuments.