PSExecAImpl.mesa
Copyright (C) Xerox Corporation 1983, 1984, 1985, 1986. All rights reserved.
Last edited by Jacks 13-Dec-85 16:43:40
Tim Diebert: October 23, 1986 1:46:12 pm PDT
Ruseli Binsol: December 8, 1986 10:08:17 am PST
DIRECTORY
BasicTime USING [Unpacked],
CHEntries USING [PrimaryData],
CHPIDs USING [ps],
CHNameP2V0 USING [Name],
IO USING [STREAM],
NSExec USING [BroadcastAsyncMessage, CheckForAbort, ClientID, Error, ExecProc, GetTTY, Handle, OutputHandle, UserName],
NSString USING [AppendCharacter, AppendDecimal, CopyString, LogicalLength, MakeString, nullString, String, TruncateString],
NSTTY USING [SetLinePosition],
PrintingTypes USING [Option],
PSAssignedTypes USING [tSelfRegStableData],
PSCommand USING [allDocuments, CancelDocument, DocumentFilter, DocumentProc, DocumentStatus, Error, FaxLocalPrintStatus, FaxTransmitStatus, GetPrintServiceStatus, ListDocuments, noDocuments, ResetStatistics, ShutDownEngine, SpecificDocStatus, StartDiagnosticMode, StartPrinting, StartQueuing, StopPrinting, StopQueuing, WakeUpEngine],
PSExec USING [GetClientID],
PSExecInternal USING [ChoiceList, KeyList, KeyListRep, RegCode],
PSExecMessages USING [Key],
PSKMessages USING [GetHandle],
PSState USING [maxStopReasonLength, StateHandle],
Rope USING [ROPE, Substr, ToRefText],
SelfReg USING [Register, RegisterCode, UnRegister, UnRegisterCode],
TextInput USING [GetChoice, GetText, GetYesNo],
TTY USING [Handle],
XFormat USING [Blanks, CR, Handle, NSLine, NSString],
XMessage USING [Get, GetList, Handle, MsgKey, MsgKeyList, Compose, StringArray];
XNSAuth USING [Key];
PSExecAImpl: CEDAR PROGRAM
IMPORTS NSExec, NSString, NSTTY, PSCommand, PSExec, PSKMessages, Rope, TextInput, XFormat, XMessage
EXPORTS PSExecInternal = BEGIN
OPEN CHName: CHNameP2V0;
STREAM: TYPE ~ IO.STREAM;
ROPE: TYPE ~ Rope.ROPE;
printServiceName: PUBLIC CHName.Name ← [NIL, NIL, NIL]; --exported by PSExecInternal; set in RegisterServiceAtClearinghouse proc.
psClientID: NSExec.ClientID ← PSExec.GetClientID[];
nsNil: NSString.String = NIL;
keySeq: TYPE ~ PSExecInternal.KeyList;
choiceSeq: TYPE ~ PSExecInternal.ChoiceList;
Message domain handle:
execMsgs: XMessage.Handle ← PSKMessages.GetHandle[exec];
**********************************
Command Processing Routines:
**********************************
DisplayDocuments: PUBLIC NSExec.ExecProc = BEGIN
ENABLE NSExec.Error => IF type = invalidExec THEN GOTO Exit;
tty: TTY.Handle ← NSExec.GetTTY[exec];
outputHandle: XFormat.Handle ← NSExec.OutputHandle[exec];
choices: CARDINAL = 4;
truncatedSenderLength: CARDINAL = 22;
truncatedStatusLength: CARDINAL = 23;
truncatedDocLength: CARDINAL = 27;
truncatedXmitStatusLength: CARDINAL = 31;
truncatedDestLength: CARDINAL = 22;
statusPosition: CARDINAL = 23;
docNamePosition: CARDINAL = 47;
pagesPosition: CARDINAL = 75;
xMitStatusPosition: CARDINAL = 2;
destPosition: CARDINAL = 34;
dateTimePosition: CARDINAL = 57;
phoneTimePosition: CARDINAL = 72;
printingOption: PrintingTypes.Option ← PSCommand.GetPrintServiceStatus[].option;
docsDisplayed: CARDINAL ← 0;
msgKeys: PSExecInternal.KeyList ← NEW[PSExecInternal.KeyListRep[choices]];
queueChoices: choiceSeq ← NEW[XMessage.StringArray[choices]];
filter: PSCommand.DocumentFilter ← PSCommand.noDocuments;
specificStatusFilter: BOOLEANFALSE;
allowSpecificStatus: PACKED ARRAY PSCommand.SpecificDocStatus OF BOOLEANALL[FALSE];
senderName: CHName.Name;
msgKeys.keys[0] ← mInProgDocs; msgKeys.keys[1] ← mUnCompDocs;
msgKeys.keys[2] ← mCompDocs; msgKeys.keys[3] ← mAllDocs;
BEGIN ENABLE UNWIND => NULL;
CheckFilter: PSCommand.DocumentProc = BEGIN
[document: DocumentAttributes] RETURNS [continue: BOOLEAN ← TRUE]--
status: PSCommand.SpecificDocStatus ← GetSpecificDocStatus[document.status];
IF allowSpecificStatus[status] THEN
[] ← DisplayDocument[document];
END; --CheckFilter
DisplayDocument: PSCommand.DocumentProc = BEGIN
[document: DocumentAttributes] RETURNS [continue: BOOLEAN ← TRUE]--
freeThisString: NSString.String;
***Display sender name:
BEGIN
senderName ← CHName.NameFieldsFromString[document.sender
! CHName.Error => GOTO NoSenderName];
senderName.object ← Rope.Substr[senderName.object, truncatedSenderLength];
XFormat.NSString[outputHandle, Rope.ToRefText[senderName.object]];
EXITS NoSenderName => XFormat.NSString[outputHandle, M[mUnreadableName]];
END;
***Display document status:
NSTTY.SetLinePosition[tty, statusPosition];
Message file string is copied so it can be truncated...
freeThisString ← StringForDocStatus[document.status, printingOption];
freeThisString ← NSString.TruncateString[freeThisString, truncatedStatusLength];
XFormat.NSString[outputHandle, freeThisString];
***Display document name:
NSTTY.SetLinePosition[tty, docNamePosition];
IF NSString.LogicalLength[document.name] # 0
THEN BEGIN
document.name ← NSString.TruncateString[document.name, truncatedDocLength];
XFormat.NSString[outputHandle, document.name];
END
ELSE XFormat.NSString[outputHandle, M[mAnonymous]];
***Display page count:
IF document.pagesDecomposed > 0 THEN BEGIN
NSTTY.SetLinePosition[tty, pagesPosition];
XFormat.NSString[outputHandle, NSString.AppendDecimal[NIL, document.pagesDecomposed]];
END;
XFormat.CR[outputHandle];
IF printingOption = fax495 THEN NULL;
<<There could be data for documents printed on a fax, even though the printing option has been changed to something else. Only print the fax-specific status, if the printing option is a fax.>>
<<THIS PROCEDURE DEALS WITH FAX WHICH IS NOT IN CEDAR>>
WITH d: document SELECT FROM
fax495 => BEGIN OPEN d.faxStatus;
unpackedTime: Time.Unpacked;
sUnpackedTime: LONG STRING ← [20];
sMinutes: LONG STRING ← [8];
sSeconds: LONG STRING ← [8];
stringArray: REF [0..2) OF NSString.String;
minutes, seconds: CARDINAL ← 0;
IF localPrint # null THEN BEGIN
***Display local print status:
NSTTY.SetLinePosition[tty, xMitStatusPosition];
Message file string is copied so it can be truncated...
freeThisString ← NSString.CopyString[
PSExecInternal.execHeap, StringForFaxLocalPrintStatus[d.status, localPrint]];
freeThisString ← NSString.TruncateString[
freeThisString, truncatedXmitStatusLength];
XFormat.NSString[outputHandle, freeThisString];
NSString.FreeString[z: PSExecInternal.execHeap, s: freeThisString];
***Display destination "Local":
NSTTY.SetLinePosition[tty, destPosition];
XFormat.NSString[outputHandle, M[mLocal]];
***Display completion date:
IF localPrint IN [printed..localFaxFailure] AND
localPrintCompletionDate # BasicTime.nullGMT THEN BEGIN --display completion time
NSTTY.SetLinePosition[tty, dateTimePosition];
unpackedTime ← BasicTime.Unpack[localPrintCompletionDate];
sUnpackedTime.length ← 0;
Time.Append[sUnpackedTime, unpackedTime];
sUnpackedTime ← ShortenDateString[sUnpackedTime];
XFormat.NSString[outputHandle, Str[sUnpackedTime]];
END;
IO.PutChar[outputHandle, '\n];
END;
FOR i: CARDINAL IN [0..phoneNumberCount) DO
***Display transmit status:
NSTTY.SetLinePosition[tty, xMitStatusPosition];
Put "will retry" on the end of status if applicable...
IF transmitData[i].willRetry THEN BEGIN
freeThisStringToo: NSString.String ← NSString.nullString;
SELECT transmitData[i].transmit FROM
transmitError => BEGIN
stringArray[0] ← transmitData[i].errorCode;
freeThisStringToo ← XMessage.Compose[
M[mShortXmitError], DESCRIPTOR[BASE[stringArray], 1], PSExecInternal.execHeap];
stringArray[0] ← freeThisStringToo;
END;
localFaxFailure => BEGIN
stringArray[0] ← transmitData[i].errorCode;
freeThisStringToo ← XMessage.Compose[
M[mShortFaxFailure], DESCRIPTOR[BASE[stringArray], 1], PSExecInternal.execHeap];
stringArray[0] ← freeThisStringToo;
END;
ENDCASE => stringArray[0] ← StringForFaxTransmitStatus[
status: d.status, faxStatus: transmitData[i].transmit, willRetry: TRUE];
freeThisString ← XMessage.Compose[
M[mWillRetry], DESCRIPTOR[BASE[stringArray], 1], PSExecInternal.execHeap];
NSString.FreeString[z: PSExecInternal.execHeap, s: freeThisStringToo];
END
ELSE
SELECT transmitData[i].transmit FROM
transmitError => BEGIN
stringArray[0] ← transmitData[i].errorCode;
freeThisString ← XMessage.Compose[
M[mTransmitError], DESCRIPTOR[BASE[stringArray], 1], PSExecInternal.execHeap];
END;
localFaxFailure => BEGIN
stringArray[0] ← transmitData[i].errorCode;
freeThisString ← XMessage.Compose[
M[mFaxFailure], DESCRIPTOR[BASE[stringArray], 1], PSExecInternal.execHeap];
END;
ENDCASE => freeThisString ← NSString.CopyString[
z: PSExecInternal.execHeap, s: StringForFaxTransmitStatus[
status: d.status, faxStatus: transmitData[i].transmit, willRetry: FALSE]];
freeThisString ← NSString.TruncateString[
s: freeThisString, bytes: truncatedXmitStatusLength];
XFormat.NSString[outputHandle, freeThisString];
NSString.FreeString[z: PSExecInternal.execHeap, s: freeThisString];
***Display destination phone number:
NSTTY.SetLinePosition[tty, destPosition];
transmitData[i].phoneNumber ← NSString.TruncateString[
s: transmitData[i].phoneNumber, bytes: truncatedDestLength];
XFormat.NSString[outputHandle, transmitData[i].phoneNumber];
***Display completion date:
IF transmitData[i].transmit IN [transmitted..localFaxFailure]
AND transmitData[i].completionDate # BasicTime.nullGMT THEN BEGIN
***Display completion time:
NSTTY.SetLinePosition[tty, dateTimePosition];
unpackedTime ← BasicTime.Unpack[transmitData[i].completionDate];
sUnpackedTime.length ← 0;
Time.Append[sUnpackedTime, unpackedTime];
sUnpackedTime ← ShortenDateString[sUnpackedTime];
XFormat.NSString[outputHandle, Str[sUnpackedTime]];
***Display phone call elapsed time:
IF transmitData[i].phoneCallElapsedTime # 0 THEN BEGIN
NSTTY.SetLinePosition[tty, phoneTimePosition];
minutes ← CARDINAL[transmitData[i].phoneCallElapsedTime / 60];
seconds ← CARDINAL[transmitData[i].phoneCallElapsedTime MOD 60];
sMinutes.length ← 0;
sSeconds.length ← 0;
String.AppendDecimal[sMinutes, minutes];
IF seconds < 10 THEN String.AppendChar[s: sSeconds, c: '0];
String.AppendDecimal[sSeconds, seconds];
stringArray[0] ← Str[sMinutes];
stringArray[1] ← Str[sSeconds];
freeThisString ← XMessage.Compose[
M[mPhoneTime], DESCRIPTOR[stringArray], PSExecInternal.execHeap];
XFormat.NSString[outputHandle, freeThisString];
NSString.FreeString[z: PSExecInternal.execHeap, s: freeThisString];
END
END;
IO.PutChar[outputHandle, '\n];
ENDCASE;
ENDLOOP;
END;
docsDisplayed ← docsDisplayed + 1;
IF docsDisplayed MOD 4 = 0 THEN --Check for user abort every 4 documents.
IF NSExec.CheckForAbort[exec] = TRUE THEN continue ← FALSE;
END; --DisplayDocument
GetList[choices, msgKeys, queueChoices];
SELECT TextInput.GetChoice[tty: tty, prompt: nsNil, choices: queueChoices, default: 1] FROM
0 => filter.status[inProgress] ← TRUE;
1 => filter.status[pending] ← filter.status[inProgress] ← filter.status[held] ← TRUE;
2 => BEGIN
filter ← PSCommand.allDocuments;
filter.status[pending] ← filter.status[inProgress] ← filter.status[held] ← FALSE;
END;
3 => filter ← PSCommand.allDocuments;
ENDCASE => {outputHandle.NSLine[M[mInvalidChoice]]; GOTO Exit};
outputHandle.NSLine[M[mDocList]];
IF printingOption = fax495 THEN outputHandle.NSLine[M[mFaxDocList]];
XFormat.CR[outputHandle];
IF specificStatusFilter
THEN PSCommand.ListDocuments[CheckFilter, filter]
ELSE PSCommand.ListDocuments[DisplayDocument, filter];
XFormat.CR[outputHandle];
DisplayCount[exec, docsDisplayed, mDocsListed];
END; --Enable clause and code.
EXITS Exit => NULL;
END; --DisplayDocuments
CancelDocuments: PUBLIC NSExec.ExecProc = BEGIN
The current implementation puts up a menu of particular groups of documents to cancel. If we allow the users to cancel individual documents in the future, be sure to catch the signal PSCommand.Error[documentNotFound].
ENABLE NSExec.Error => IF type = invalidExec THEN GOTO Exit;
tty: TTY.Handle ← NSExec.GetTTY[exec];
outputHandle: XFormat.Handle ← NSExec.OutputHandle[exec];
printingOption: PrintingTypes.Option ← PSCommand.GetPrintServiceStatus[].option;
docsCanceled: CARDINAL ← 0;
choices: CARDINAL = 5;
msgKeys: PSExecInternal.KeyList ← NEW[PSExecInternal.KeyListRep[choices]];
queueChoices: PSExecInternal.ChoiceList ← NEW[XMessage.StringArray[choices]];
filter: PSCommand.DocumentFilter ← PSCommand.noDocuments;
specificStatusFilter: BOOLEANFALSE; --If true check specific status filter (allowSpecificStatus) before cancelling doc.
faxFilter: BOOLEANFALSE; --If true check fax status filters (allowFaxLocalStatus and allowFaxTransmitStatus) before cancelling doc.
allowSpecificStatus: PACKED ARRAY PSCommand.SpecificDocStatus OF BOOLEANALL[FALSE];
allowFaxLocalStatus: PACKED ARRAY PSCommand.FaxLocalPrintStatus OF BOOLEANALL[FALSE];
allowFaxTransmitStatus: PACKED ARRAY PSCommand.FaxTransmitStatus OF BOOLEANALL[FALSE];
CheckFilter: PSCommand.DocumentProc =
[document: DocumentAttributes] RETURNS [continue: BOOLEAN ← TRUE]--
BEGIN
intStatus: PSCommand.SpecificDocStatus ←
GetSpecificDocStatus[document.status];
IF specificStatusFilter AND NOT allowSpecificStatus[intStatus] THEN RETURN;
IF faxFilter THEN TRUSTED BEGIN
WITH d: document SELECT FROM
fax495 => BEGIN
IF allowFaxLocalStatus[d.faxStatus.localPrint] THEN GOTO allowed;
FOR p: CARDINAL IN [0..d.faxStatus.phoneNumberCount) DO
IF allowFaxTransmitStatus[d.faxStatus.transmitData[p].transmit] THEN
GOTO allowed;
ENDLOOP;
RETURN; --none of the "allowed" statuses found
END;
ENDCASE => NULL; --not a fax document
EXITS allowed => NULL;
END;
continue ← CancelDocument[document];
END; --CheckFilter
CancelDocument: PSCommand.DocumentProc =
[document: DocumentAttributes] RETURNS [continue: BOOLEAN ← TRUE]--
TRUSTED BEGIN
stringArray: REF XMessage.StringArray ← NEW[XMessage.StringArray[2]];
newStatus: PSCommand.DocumentStatus;
IF NSExec.CheckForAbort[exec] THEN RETURN [continue: FALSE];
newStatus ← PSCommand.CancelDocument[document.id];
IF newStatus.simple = canceled THEN BEGIN
stringArray[0] ←
IF document.name.length = 0 THEN M[mAnonymous]
ELSE document.name;
stringArray[1] ← StringForDocStatus[newStatus, printingOption];
ExpandKeyAndPrint[exec, mDocListTerse, stringArray];
docsCanceled ← docsCanceled + 1;
END;
END; --CancelDocument
For feps9700 mMarkingDoc becomes mForwardingDoc...
IF printingOption = feps9700
THEN {msgKeys.keys[0] ← mFormatDoc; msgKeys.keys[1] ← mForwardingDoc; msgKeys.keys[2] ← mInProgDocs; msgKeys.keys[3] ← mQdDocs;
msgKeys.keys[4] ← mAllDocs}
ELSE {msgKeys.keys[0] ← mFormatDoc; msgKeys.keys[1] ← mMarkingDoc;
msgKeys.keys[2] ← mInProgDocs; msgKeys.keys[3] ← mQdDocs;
msgKeys.keys[4] ← mAllDocs};
GetList[choices, msgKeys, queueChoices];
SELECT TextInput.GetChoice[tty: tty, prompt: nsNil, choices: queueChoices] FROM
0 => BEGIN
filter.status[inProgress] ← TRUE;
specificStatusFilter ← TRUE;
allowSpecificStatus[decomposing] ← TRUE;
IF printingOption = feps9700 THEN
allowSpecificStatus[decomposed] ←
allowSpecificStatus[merging] ← TRUE;
END;
1 => BEGIN
filter.status[inProgress] ← TRUE;
specificStatusFilter ← faxFilter ← TRUE;
allowSpecificStatus[marking] ←
allowSpecificStatus[forwarding] ←
allowSpecificStatus[faxStatus] ← TRUE;
allowFaxLocalStatus[marking] ←
allowFaxTransmitStatus[transmitting] ← TRUE;
END;
2 => filter.status[inProgress] ← TRUE;
3 => filter.status[pending] ← TRUE;
4 => BEGIN
filter.status[pending] ← TRUE;
filter.status[inProgress] ← TRUE;
END;
ENDCASE => {outputHandle.NSLine[M[mInvalidChoice]]; GOTO Exit;};
IF Confirm[exec] THEN BEGIN
IF specificStatusFilter OR faxFilter THEN
PSCommand.ListDocuments[CheckFilter, filter]
ELSE
PSCommand.ListDocuments[CancelDocument, filter];
DisplayCount[exec, docsCanceled, mDocsCanceled];
END;
EXITS Exit => NULL;
END; --CancelDocuments
StartQueuingAndPrinting: PUBLIC NSExec.ExecProc =
BEGIN
ENABLE NSExec.Error => IF type = invalidExec THEN GOTO Exit;
name: CHName.Name ← NSExec.UserName[
exec ! NSExec.Error => GOTO Exit];
state: PSState.StateHandle ← PSCommand.GetPrintServiceStatus[];
stringArray: REF XMessage.StringArray ← NEW [XMessage.StringArray[2]];
stringArray: ARRAY [0..2) OF NSString.String ← ALL[nsNil];
freeThisString: NSString.String;
stopReasonDisplayed: BOOLEANFALSE;
Display stop queuing reason, if any:
IF state.lastUserToStopQueuing.length > 0 AND
state.lastStopQueuingReason.length > 0 THEN BEGIN
stringArray.data[0] ← state.lastStopQueuingReason;
freeThisString ← XMessage.Compose[M[mReason], stringArray];
stringArray.data[0] ← state.lastUserToStopQueuing;
stringArray.data[1] ← freeThisString;
ExpandKeyAndPrint[exec, mQueuingStoppedBy, stringArray];
stopReasonDisplayed ← TRUE;
END;
Display stop printing reason, if any:
IF state.lastUserToStopPrinting.length > 0 AND
state.lastStopPrintingReason.length > 0 THEN BEGIN
stringArray[0] ← state.lastStopPrintingReason;
freeThisString ← XMessage.Compose[M[mReason], stringArray];
stringArray[0] ← state.lastUserToStopPrinting;
stringArray[1] ← freeThisString;
ExpandKeyAndPrint[exec, mPrintingStoppedBy, stringArray];
NSString.FreeString[z: PSExecInternal.execHeap, s: freeThisString];
stopReasonDisplayed ← TRUE;
END;
IF stopReasonDisplayed THEN
IF NOT ConfirmExpanded[exec, mStart] THEN RETURN;
StartQueuingInternal[exec, name];
StartPrintingInternal[exec, name];
EXITS Exit => NULL;
END; --StartQueuingAndPrinting
StopQueuingAndPrinting: PUBLIC NSExec.ExecProc =
BEGIN
ENABLE NSExec.Error => IF type = invalidExec THEN GOTO Exit;
tty: TTY.Handle ← NSExec.GetTTY[exec];
name: CHName.Name ← NSExec.UserName[
exec ! NSExec.Error => GOTO Exit];
stopReason: NSString.String ← NSString.MakeString[
bytes: PSState.maxStopReasonLength];
stopReason ← TextInput.GetText[tty: tty,
prompt: M[mEnterReason], text: stopReason,
minLength: 0, maxLength: PSState.maxStopReasonLength];
StopQueuingInternal[exec, name, stopReason];
StopPrintingInternal[exec, name, stopReason];
NSString.FreeString[z: PSExecInternal.execHeap, s: stopReason];
EXITS Exit => NULL;
END; --StopQueuingAndPrinting
StartPrinting: PUBLIC NSExec.ExecProc = BEGIN
ENABLE NSExec.Error => IF type = invalidExec THEN GOTO Exit;
name: CHName.Name ← NSExec.UserName[
exec ! NSExec.Error => GOTO Exit];
state: PSState.StateHandle ← PSCommand.GetPrintServiceStatus[];
stringArray: REF XMessage.StringArray ← NEW [XMessage.StringArray[2]];
freeThisString: NSString.String;
Display stop printing reason, if any:
IF state.lastUserToStopPrinting.length > 0 AND
state.lastStopPrintingReason.length > 0 THEN BEGIN
stringArray[0] ← state.lastStopPrintingReason;
freeThisString ← XMessage.Compose[M[mReason], stringArray];
stringArray[0] ← state.lastUserToStopPrinting;
stringArray[1] ← freeThisString;
ExpandKeyAndPrint[exec, mPrintingStoppedBy, stringArray];
NSString.FreeString[z: PSExecInternal.execHeap, s: freeThisString];
IF NOT ConfirmExpanded[exec, mStartPrinting] THEN RETURN;
END;
StartPrintingInternal[exec, name];
EXITS Exit => NULL;
END; --StartPrinting
StopPrinting: PUBLIC NSExec.ExecProc = BEGIN
ENABLE NSExec.Error => IF type = invalidExec THEN GOTO Exit;
tty: TTY.Handle ← NSExec.GetTTY[exec];
name: CHName.Name ← NSExec.UserName[
exec ! NSExec.Error => GOTO Exit];
stopReason: NSString.String ← NSString.MakeString[bytes: PSState.maxStopReasonLength];
BEGIN ENABLE UNWIND =>
NSString.FreeString[z: PSExecInternal.execHeap, s: stopReason];
stopReason ← TextInput.GetText[tty: tty, prompt: M[mEnterReason], text: stopReason,
minLength: 0, maxLength: PSState.maxStopReasonLength];
StopPrintingInternal[exec, name, stopReason];
NSString.FreeString[z: PSExecInternal.execHeap, s: stopReason];
END; --Enable clause and code
EXITS Exit => NULL;
END; --StopPrinting
StartQueuing: PUBLIC NSExec.ExecProc = BEGIN
ENABLE NSExec.Error => IF type = invalidExec THEN GOTO Exit;
name: CHName.Name ← NSExec.UserName[exec ! NSExec.Error => GOTO Exit];
state: PSState.StateHandle ← PSCommand.GetPrintServiceStatus[];
stringArray: REF XMessage.StringArray ← NEW [XMessage.StringArray[2]];
freeThisString: NSString.String;
Display stop queuing reason, if any:
IF state.lastUserToStopQueuing.length > 0 AND
state.lastStopQueuingReason.length > 0 THEN BEGIN
stringArray[0] ← state.lastStopQueuingReason;
freeThisString ← XMessage.Compose[M[mReason], stringArray];
stringArray[0] ← state.lastUserToStopQueuing;
stringArray[1] ← freeThisString;
ExpandKeyAndPrint[exec, mQueuingStoppedBy, stringArray];
NSString.FreeString[PSExecInternal.execHeap, expandedString];
IF NOT ConfirmExpanded[exec, mStartSpooling] THEN RETURN;
END;
StartQueuingInternal[exec, name];
EXITS Exit => NULL;
END; --StartQueuing
StopQueuing: PUBLIC NSExec.ExecProc = BEGIN
ENABLE NSExec.Error => IF type = invalidExec THEN GOTO Exit;
tty: TTY.Handle ← NSExec.GetTTY[exec];
name: CHName.Name ← NSExec.UserName[
exec ! NSExec.Error => GOTO Exit];
stopReason: NSString.String ← NSString.MakeString[bytes: PSState.maxStopReasonLength];
BEGIN ENABLE UNWIND =>
NSString.FreeString[z: PSExecInternal.execHeap, s: stopReason];
stopReason ← TextInput.GetText[tty: tty,
prompt: M[mEnterReason], text: stopReason,
minLength: 0, maxLength: PSState.maxStopReasonLength];
StopQueuingInternal[exec, name, stopReason];
END; --Enable clause and code
EXITS Exit => NULL;
END; --StopQueuing
StartDiagnostic: PUBLIC NSExec.ExecProc = BEGIN
ENABLE NSExec.Error => IF type = invalidExec THEN GOTO Exit;
outputHandle: XFormat.Handle ← NSExec.OutputHandle[exec];
IF Confirm[exec] THEN BEGIN
PSCommand.StartDiagnosticMode[];
outputHandle.Blanks[2];
outputHandle.NSLine[M[mDone]];
END;
EXITS Exit => NULL;
END; --StartDiagnostic
ShutDownPrinter: PUBLIC NSExec.ExecProc = BEGIN
ENABLE NSExec.Error => IF type = invalidExec THEN GOTO Exit;
IF Confirm[exec] THEN PSCommand.ShutDownEngine[];
EXITS Exit => NULL;
END; --ShutDownPrinter
WakeUpPrinter: PUBLIC NSExec.ExecProc = BEGIN
ENABLE NSExec.Error => IF type = invalidExec THEN GOTO Exit;
PSCommand.WakeUpEngine[];
EXITS Exit => NULL;
END; --WakeUpPrinter
ResetStatistics: PUBLIC NSExec.ExecProc = BEGIN
ENABLE NSExec.Error => IF type = invalidExec THEN GOTO Exit;
IF Confirm[exec] THEN PSCommand.ResetStatistics[];
EXITS Exit => NULL;
END; --ResetStatistics
RenamePrintService: PUBLIC NSExec.ExecProc = BEGIN
Rename the Print Service with the Clearinghouse.
ENABLE NSExec.Error => IF type = invalidExec THEN GOTO Exit;
outputHandle: XFormat.Handle ← NSExec.OutputHandle[exec];
BEGIN --Another nested block added so that Aborted EXIT may reference outputHandle.
IF Confirm[exec] THEN BEGIN
registerCode, unRegisterCode: PSExecInternal.RegCode;
Delete old service name from Clearinghouse:
XFormat.CR[outputHandle];
outputHandle.Blanks[4];
outputHandle.NSLine[M[mDeleteOldName]];
SELECT unRegisterCode ← DeleteServiceFromClearinghouse[exec] FROM
aborted => GOTO Aborted;
checkClearinghouse => BEGIN
outputHandle.Blanks[8];
outputHandle.NSLine[M[mCheckClearinghouse]];
END;
ENDCASE => NULL;
Proceed to register new name with Clearinghouse:
XFormat.CR[outputHandle];
outputHandle.Blanks[4];
outputHandle.NSLine[M[mAddNewName]];
[registerCode,] ← RegisterServiceAtClearinghouse[exec];
SELECT registerCode FROM
aborted => GOTO Aborted;
checkClearinghouse => BEGIN
outputHandle.Blanks[8];
outputHandle.NSLine[M[mCheckClearinghouse]];
END;
ENDCASE => NULL;
XFormat.CR[outputHandle];
outputHandle.Blanks[4];
outputHandle.NSLine[M[mBootForNameOnBanner]];
END;
EXITS
Aborted => BEGIN
XFormat.CR[outputHandle];
outputHandle.Blanks[4];
outputHandle.NSLine[M[mProblems]];
outputHandle.Blanks[4];
outputHandle.NSLine[M[mTryAgainLater]];
outputHandle.Blanks[4];
outputHandle.NSLine[M[mCheckClearinghouse]];
END;
END; --Extra nested block.
EXITS Exit => NULL;
END; --RenamePrintService
***************************
The 'internal' procs below were created rather than having Start and Stop call the StartPrinting, etc., ExecProcs so that if the user cancels the command in the middle of Start or Stop, they will not try to continue. (I.e. NSCommand.Error should be caught in only one place for each command processor.
StartPrintingInternal: PROCEDURE [exec: NSExec.Handle, user: CHName.Name] = BEGIN
outputHandle: XFormat.Handle ← NSExec.OutputHandle[exec];
stringArray: REF XMessage.StringArray ← NEW [XMessage.StringArray[2]];
outputHandle.NSLine[M[mStartingPrinting]];
PSCommand.StartPrinting[user
! PSCommand.Error => IF problem.errorType = documentInProgress THEN {
Couldn't catalog fonts because a document (presumably a test
pattern) was in progress. So printing wasn't started.
outputHandle.NSLine[M[mUnableToCatalogFonts]];
GOTO Exit}];
IF NOT PSCommand.GetPrintServiceStatus[].internalControl.markerEnabled THEN
stringArray[0] ← M[mCurrentlyPreempted];
outputHandle.Blanks[2];
ExpandKeyAndPrint[exec, mDoneExpanded, stringArray];
EXITS Exit => NULL;
END; --StartPrintingInternal
StartQueuingInternal: PROCEDURE [ exec: NSExec.Handle, user: CHName.Name] = BEGIN
stringArray: REF XMessage.StringArray ← NEW [XMessage.StringArray[2]];
PSCommand.StartQueuing[user];
IF PSCommand.GetPrintServiceStatus[].internalControl.spooler # enabled THEN
stringArray[0] ← M[mCurrentlyPreempted];
ExpandKeyAndPrint[exec, mQueuingStarted, stringArray];
END; --StartQueuingInternal
StopPrintingInternal: PROCEDURE [ exec: NSExec.Handle, user: CHName.Name, reason: NSString.String ← NSString.nullString] = BEGIN
outputHandle: XFormat.Handle ← NSExec.OutputHandle[exec];
outputHandle.NSLine[M[mStoppingPrinting]];
PSCommand.StopPrinting[user, reason];
outputHandle.Blanks[2];
outputHandle.NSLine[M[mDone]];
END; --StopPrintingInternal
StopQueuingInternal: PROCEDURE [ exec: NSExec.Handle, user: CHName.Name, reason: NSString.String ← NSString.nullString] = BEGIN
outputHandle: XFormat.Handle ← NSExec.OutputHandle[exec];
outputHandle.NSLine[M[mStoppingQueuing]];
PSCommand.StopQueuing[user, reason];
outputHandle.Blanks[2];
outputHandle.NSLine[M[mDone]];
END; --StopQueuingInternal
*********************
Support routines:
*********************
Confirm: PROCEDURE [exec: NSExec.Handle] RETURNS [response: BOOLEAN] = BEGIN
tty: TTY.Handle ← NSExec.GetTTY[exec];
response ← TextInput.GetYesNo[tty, M[mConfirm], yes] = yes;
END; --Confirm
ConfirmExpanded: PROCEDURE [exec: NSExec.Handle, insertKey: PSExecMessages.Key] RETURNS [response: BOOLEAN] = BEGIN
tty: TTY.Handle ← NSExec.GetTTY[exec];
stringArray: REF XMessage.StringArray ← NEW[XMessage.StringArray[1]];
freeThisString: NSString.String;
stringArray.data[0] ← M[insertKey];
freeThisString ← XMessage.Compose[M[mConfirmExpanded], stringArray];
response ← TextInput.GetYesNo[tty, freeThisString, yes] = yes;
NSString.FreeString[PSExecInternal.execHeap, freeThisString];
END; --ConfirmExpanded
DeleteServiceFromClearinghouse: PUBLIC PROCEDURE [exec: NSExec.Handle] RETURNS [code: PSExecInternal.RegCode] = BEGIN
UnRegister uses self-registration to remove stable data and CH entry for the Print Service. NOTE: Per Larry Kluger 7/9/84, authProblem should be treated as non-fatal (stable data is updated) because it usually means we couldn't reach the auth service.
<<THESE ARE FILE TYPES FROM INTERFACE PSAssignedTypes>>
unRegCode: SelfReg.UnRegisterCode;
unRegCode ← SelfReg.UnRegister[
primary: CHPIDs.ps, stableType: PSAssignedTypes.tSelfRegStableData,
exec: exec, clientID: psClientID, asyncMessage: FALSE];
printServiceName ← [NIL, NIL, NIL]; --Clear global variable.
SELECT unRegCode FROM
accessProblem, userAbort, other => code ← aborted;
authProblem, noClearinghouse, alreadyAlias, inUse, noStableData => code ← checkClearinghouse;
ENDCASE => code ← ok;
END; --DeleteServiceFromClearinghouse
DisplayCount: PUBLIC PROCEDURE [exec: NSExec.Handle, count: CARDINAL, msg: PSExecMessages.Key] = BEGIN
stringArray: REF XMessage.StringArray ← NEW [XMessage.StringArray[2]];
stringArray[0] ← NEW[TEXT[10]];
ExpandKeyAndPrint[exec, msg, stringArray];
END; -- DisplayCount
ExpandKeyAndPrint: PUBLIC PROCEDURE [exec: NSExec.Handle, template: PSExecMessages.Key, stringArray: PSExecInternal.ChoiceList] = BEGIN
ExpandArrayAndPrint[exec, M[template], stringArray];
END; -- ExpandKeyAndPrint
ExpandArrayAndPrint: PUBLIC PROCEDURE [exec: NSExec.Handle, template: NSString.String, stringArray: PSExecInternal.ChoiceList] = BEGIN
outputHandle: XFormat.Handle ← NSExec.OutputHandle[exec];
expandedString: NSString.String ← XMessage.Compose[template, stringArray];
outputHandle.NSLine[expandedString];
END; -- ExpandArrayAndPrint
ExpandArrayAndPrintAsync: PUBLIC PROCEDURE [template: NSString.String,
stringArray: PSExecInternal.ChoiceList] = BEGIN --Asynchronous messages are sent to all active execs.
expandedString: NSString.String ← XMessage.Compose[template, stringArray];
NSExec.BroadcastAsyncMessage[expandedString, psClientID]; --send async message to all active execs
NSString.FreeString[PSExecInternal.execHeap, expandedString];
END; -- ExpandArrayAndPrintAsync
Proc for getting a list of messages via XMessage and converting them to NSStrings
GetList: PUBLIC PROCEDURE [length: CARDINAL, keys: PSExecInternal.KeyList,
stringArray: PSExecInternal.ChoiceList] = BEGIN
maxStrings: CARDINAL = 10;
xs: REF XMessage.StringArray ← NEW[XMessage.StringArray[maxStrings]];
xKeys: REF XMessage.MsgKeyList ← NEW[XMessage.MsgKeyList[maxStrings]];
IF length > maxStrings THEN ERROR;
FOR i: CARDINAL IN [0..length) DO
xKeys.data[i] ← ORD[keys.keys[i]];
ENDLOOP;
XMessage.GetList[execMsgs, xKeys, xs];
FOR i: CARDINAL IN [0..length) DO
stringArray[i] ← xs.data[i];
ENDLOOP;
END;
GetSpecificDocStatus: PROCEDURE [status: PSCommand.DocumentStatus]
RETURNS
[specificStatus: PSCommand.SpecificDocStatus] = BEGIN
WITH s: status SELECT FROM
pending => specificStatus ← s.specific;
inProgress => specificStatus ← s.specific;
rejected => specificStatus ← s.specific;
aborted => specificStatus ← s.specific;
canceled => specificStatus ← s.specific;
ENDCASE => specificStatus ← null;
END; --GetSpecificDocStatus
RegisterServiceAtClearinghouse: PUBLIC PROCEDURE [exec: NSExec.Handle] RETURNS [code: PSExecInternal.RegCode, serviceName: CHName.Name ← [NIL, NIL, NIL]] =
Register uses self registratin to prompt operator for new service name, creates new CH entry and stores name in stable data.
NOTE: Per Larry Kluger 7/9/84, authProblem should be treated as non-fatal (stable data is updated), because it usually means we couldn't reach the auth service.
BEGIN --Exported by PSExecInternal.
<<COMMENTED OUT BECAUSE THIS IMPLEMENTATION IS NOT CURRENTLY
SUPPORTED IN CEDAR>>
regCode: SelfReg.RegisterCode;
chDesc: CHEntries.PrimaryData ← NSString.nullString;
authKey: XNSAuth.Key;
[regCode, serviceName, chDesc, authKey] ← SelfReg.Register[
primary: CHPIDs.ps, stableType: PSAssignedTypes.tSelfRegStableData,
exec: exec, clientID: psClientID, operator: TRUE,
asyncMessage: FALSE, z: PSExecInternal.execHeap];
printServiceName ← serviceName; --Save name in global variable.
SELECT regCode FROM
alreadyAlias, inUse, badServiceName, noOperator, accessProblem, userAbort, other => code ← aborted;
authProblem, noClearinghouse => code ← checkClearinghouse;
ENDCASE => code ← ok;
END; --RegisterServiceAtClearinghouse
ShortenDateString: PROCEDURE [sDate: NSString.String] RETURNS [sShortDate: NSString.String] =
Returns date string with only day, month, hour and minutes stored in place of old string.
BEGIN
sOldDate: NSString.String ← NSString.CopyString[s: sDate];
onceAround: BOOLEANFALSE;
i: CARDINAL ← 0;
hyphen: CHARACTER = '-;
colon: CHARACTER = ':;
blank: CHARACTER = ' ;
sDate.length ← 0;
sShortDate ← sDate;
Copy day and month, but skip year:
UNTIL sOldDate.text[i] = hyphen AND onceAround DO
sShortDate ← NSString.AppendCharacter[sShortDate, [0, LOOPHOLE[sOldDate.text[i]]]];
IF sOldDate.text[i] = hyphen THEN onceAround ← TRUE;
i ← i + 1;
ENDLOOP;
onceAround ← FALSE;
UNTIL sOldDate.text[i] = blank DO i ← i + 1; ENDLOOP;
Copy hours and minutes, but skip seconds:
UNTIL sOldDate.text[i] = colon AND onceAround DO
sShortDate ← NSString.AppendCharacter[sShortDate, [0, LOOPHOLE[sOldDate.text[i]]]];
IF sOldDate.text[i] = colon THEN onceAround ← TRUE;
i ← i + 1;
ENDLOOP;
NSString.FreeString[z: PSExecInternal.execHeap, s: sOldDate];
END; --ShortenDateString
StringForDocStatus: PROCEDURE [status: PSCommand.DocumentStatus, printingOption: PrintingTypes.Option] RETURNS [NSString.String] = BEGIN
WITH s: status SELECT FROM
pending => RETURN [M[
SELECT s.specific FROM
restart => mRequeued,
spooled => mSpooled,
spooling => mSpooling,
ENDCASE => mQuestion]];
inProgress => RETURN [M[
SELECT s.specific FROM
decomposing, merging => mBeingFormatted,
decomposed => IF printingOption = feps9700 THEN mBeingFormatted ELSE mDecomposed,
marking => mBeingPrinted,
merged => mDecomposed,
forwarding => mBeingForwarded,
faxStatus => mInProgress,
ENDCASE => mQuestion]];
completed => RETURN [M[
SELECT s.specific FROM
printed => mPrinted,
forwarded => mForwarded,
faxStatus => mCompleted,
ENDCASE => mQuestion]];
completedWithWarnings => RETURN [M[
SELECT s.specific FROM
printed => mPrinted,
forwarded => mForwarded,
faxStatus => mCompleted,
ENDCASE => mQuestion]];
rejected => RETURN [M[mSpoolFailure]];
aborted => RETURN [M[
SELECT s.specific FROM
decomposeFailure, mergeFailure => mDecomposeFailure,
markFailure => mMarkFailure,
forwardFailure => mForwardFailure,
sysRestartInSpooler => mSysRestartInSpooler,
sysRestartInDecomposer, sysRestartInMerger => mSysRestartInDecomposer,
sysRestartInMarker => mSysRestartInMarker,
sysRestartInForwarder => mSysRestartInForwarder,
sysRestartInQueue => mSysRestartInQueue,
faxStatus => mCompleted,
ENDCASE => mQuestion]];
canceled => RETURN [M[
SELECT s.specific FROM
canceledInQueue => mCanceledInQueue,
canceledInDecomposer, canceledInMerger => mCanceledInDecomposer,
canceledInMarker => mCanceledInMarker,
canceledInForwarder => mCanceledInForwarder,
faxStatus => mCanceledInMarker,
ENDCASE => mQuestion]];
ENDCASE => RETURN [M[mQuestion]];
END; --StringForDocStatus
StringForFaxLocalPrintStatus: PROCEDURE [status: PSCommand.DocumentStatus,
faxStatus: PSCommand.FaxLocalPrintStatus] RETURNS [NSString.String] = BEGIN --Returns appropriate status string for local instance of fax document. For certain rejected, canceled and aborted docs, the faxStatus does not apply.
WITH s: status SELECT FROM
rejected => RETURN [M[mAborted]]; --spoolFailure
canceled => SELECT s.specific FROM
canceledInMarker, faxStatus => NULL; --Shouldn't get canceledInMarker for fax doc.
ENDCASE => RETURN [M[mAborted]];
aborted => SELECT s.specific FROM
markFailure, sysRestartInMarker, faxStatus => NULL;
ENDCASE => RETURN [M[mAborted]];
ENDCASE;
RETURN [M[SELECT faxStatus FROM
queued => mPending,
marking => mBeingPrinted,
printed => mPrinted,
canceled => mAborted,
localFaxFailure => mMarkFailure,
purgedAtSysRestart => mAborted,
ENDCASE => mQuestion]];
END; --StringForFaxLocalPrintStatus
StringForFaxTransmitStatus: PROCEDURE [status: PSCommand.DocumentStatus,
faxStatus: PSCommand.FaxTransmitStatus, willRetry: BOOLEAN] RETURNS [NSString.String] =
BEGIN --Returns appropriate status string for transmit instance of fax document.
For certain rejected, canceled and aborted docs, the faxStatus does not apply.
WITH s: status SELECT FROM
rejected => RETURN [M[mAborted]]; --spoolFailure
canceled => SELECT s.specific FROM
canceledInMarker, faxStatus => NULL; --Shouldn't get canceledInMarker for fax doc.
ENDCASE => RETURN [M[mAborted]];
aborted => SELECT s.specific FROM
markFailure, sysRestartInMarker, faxStatus => NULL;
ENDCASE => RETURN [M[mAborted]];
ENDCASE;
RETURN [M[SELECT faxStatus FROM
queued => mPending,
transmitting => mBeingTransmitted,
transmitted => mTransmitted,
canceled => mAborted,
busy => mBusy,
noAnswer => mNoAnswer,
transmitError => mTransmitError,
invalidPhoneNumber => mBadPhoneNo,
localFaxFailure => IF willRetry THEN mShortFaxFailure ELSE mFaxFailure,
purgedAtSysRestart => mAborted,
ENDCASE => mQuestion]];
END; --StringForFaxTransmitStatus
Proc for getting NSString from XMessage key
M: PROCEDURE [key: PSExecMessages.Key] RETURNS [string: NSString.String] = {
RETURN[XMessage.Get[execMsgs, ORD[key]]]};
END. --PSExecAImpl
LOG
****EARLIER LOG ENTRIES DELETED. See archived version from 8.0.
15-Sep-84 11:39:12 - Jacks - Converted to new interfaces for 9.0: PSState, PSCommand; added code for banshee, fax295 and feps9700.
4-Oct-84 13:11:50 - Jacks - Renamed from PSTTYExecAImpl to PSExecAImpl; added selfreg routines; added NSExec.CheckForAbort to ListDocuments and CancelDocuments.
19-Oct-84 16:00:45 - Jacks - Rename ttyHeap to execHeap; added feps9700 statuses to StringForDocStatus.
16-Nov-84 9:44:41 - Jacks - Updated to latest PSCommand interface; removed TTY.Rubout catch phrases (it is caught by SCS).
19-Nov-84 14:21:43 - Jacks - Added feps9700 specific stuff to CancelDocuments.
13-Dec-84 11:37:22 - Jacks - Removed ControlMessagesExtras.
16-Jan-85 15:34:38 - Jacks - Added "ps" prefix to all new msg keys for 9.0.
28-Feb-85 15:27:03 - Jacks - Raise error to turn off public error catching during development in certain exec procs.
19-Jun-85 11:43:09 - Jacks - Added copyright notice; updated to PS Euclid interfaces; turned off public error catching during development mode in all exec procs.
28-Jun-85 15:02:54 - Jacks - Removed SetCatching calls.
18-Jul-85 15:01:18 - Jacks - Converted to XMessage.
7-Aug-85 12:56:35 - Jacks - Now catch NSName.Error on call to NameFieldsFromString.
26-Aug-85 10:45:01 - Jacks - Made arrays of booleans in DisplayDocuments and CancelDocuments PACKED ARRAYs to reduce local frame size.
10-Sep-85 13:45:50 - Jacks - Switched to PSCommandExtras.DocumentFilter because it requires less frame space.
24-Sep-85 14:24:20 - Jacks - PSCommandExtras folded into PSCommand.
15-Oct-85 9:54:00 - Jacks - Added errorCode to fax display docs.
6-Nov-85 13:07:04 - Jacks - Changed display docs default to uncompleted docs; call PSKMessages for msg handle; don't start printing if can't catalog fonts in StartPrintingInternal.
13-Dec-85 16:42:23 - Jacks - ExecMessages renamed to PSExecMessages.