XNSPrintRequestManagerImpl.Mesa
Copyright Ó 1985, 1986, 1987 by Xerox Corporation. All rights reserved.
Bill Jackson (bj) February 6, 1987 6:39:37 am PST
gbb February 10, 1987 4:27:23 pm PST
DIRECTORY
BasicTime USING [GMT, nullGMT, ToNSTime],
CedarProcess USING [Fork, ForkableProc, Process],
CHNameP2V0 USING [Name],
CrRPC USING [BulkDataXferProc, CreateClientHandle, DestroyClientHandle, Handle],
FS USING [StreamOpen],
IO USING [Close, EndOf, GetBlock, PutBlock, STREAM],
RefText USING [ObtainScratch, ReleaseScratch],
Rope USING [ROPE],
UserCredentials USING [Get, CredentialsChangeProc, RegisterForChange],
UserProfile USING [Boolean, CallWhenProfileChanges, Line, Number, ProfileChangedProc],
XNS USING [Address, unknownSocket],
XNSCH USING [LookupAddressFromRope],
XNSStream USING [waitForever],
PrintingP4V3,
XNSPrintRequestManager;
XNSPrintRequestManagerImpl: CEDAR MONITOR
IMPORTS BasicTime, CedarProcess, CrRPC, FS, IO, PrintingP4V3, RefText, UserCredentials, UserProfile, XNSCH
EXPORTS XNSPrintRequestManager ~ {
OPEN CHName: CHNameP2V0, Printing: PrintingP4V3, XNSPrintRequestManager;
ROPE: TYPE ~ Rope.ROPE;
UserProfile Tags
BANNER: ROPE ~ "Hardcopy.Banner";
CFNAME: ROPE ~ "Hardcopy.CFName";
COPYCOUNT: ROPE ~ "Hardcopy.CopyCount";
CREATEDATE: ROPE ~ "Hardcopy.CreateDate";
IPPRINTER: ROPE ~ "Hardcopy.InterpressPrinter";
KEY: ROPE ~ "Hardcopy.Key";
MEDIUM: ROPE ~ "Hardcopy.Medium";
PIGEONHOLE: ROPE ~ "Hardcopy.PigeonHole";
PAGEFIRST: ROPE ~ "Hardcopy.PageFirst";
PAGELAST: ROPE ~ "Hardcopy.PageLast";
PRINTSIZE: ROPE ~ "Hardcopy.PrintSize";
PRIORITY: ROPE ~ "Hardcopy.Priority";
STAPLED: ROPE ~ "Hardcopy.Stapled";
TWOSIDED: ROPE ~ "Hardcopy.TwoSided";
Global State (atomically altered under the monitor)
pendingPrintRequests: PrintRequestList ← NIL;
userContext: Context;
watcherProcess: CedarProcess.Process;
Request Manager Procs
ListChanged: PUBLIC CONDITION;
RegisterPrintRequest: PUBLIC ENTRY PROC [request: PrintRequest, update: StatusChangedProc ← NIL] ~ {
pendingPrintRequests ← CONS[request, pendingPrintRequests];
NOTIFY ListChanged;
};
UnRegisterPrintRequest: PUBLIC ENTRY PROC [request: PrintRequest] ~ {
SELECT TRUE FROM
(pendingPrintRequests = NIL) => {
RETURN;
};
(pendingPrintRequests.first = request) => {
pendingPrintRequests ← pendingPrintRequests.rest;
};
ENDCASE => {
FOR tail: PrintRequestList ← pendingPrintRequests, tail.rest WHILE (tail.rest # NIL) DO
IF (tail.rest.first = request) THEN {
tail.rest ← tail.rest.rest;
EXIT;
};
ENDLOOP;
};
NOTIFY ListChanged;
};
GetPrintRequestList: PUBLIC ENTRY PROC RETURNS [list: PrintRequestList] ~ {
list ← pendingPrintRequests;
};
Watcher process
WaitTilListChanged: ENTRY PROC ~ {
WAIT ListChanged;
};
WatchRequestList: CedarProcess.ForkableProc ~ {
DO
WaitTilListChanged[];
ENDLOOP;
};
Print Service Interaction
GetPrinterProperties: PUBLIC PROC [printer: ROPE] RETURNS [service: CHName.Name, answer: Printing.PrinterProperties] ~ {
addr: XNS.Address; h: CrRPC.Handle;
[service, addr] ← XNSCH.LookupAddressFromRope[printer];
addr.socket ← XNS.unknownSocket; -- Kluge for CH bug
h ← CrRPC.CreateClientHandle[class~$SPP, remote~addr];
answer ← Printing.GetPrinterProperties[h];
CrRPC.DestroyClientHandle[h];
};
GetPrinterStatus: PUBLIC PROC [printer: ROPE] RETURNS [service: CHName.Name, answer: Printing.PrinterStatus] ~ {
addr: XNS.Address; h: CrRPC.Handle;
[service, addr] ← XNSCH.LookupAddressFromRope[printer];
addr.socket ← XNS.unknownSocket; -- Kluge for CH bug
h ← CrRPC.CreateClientHandle[class~$SPP, remote~addr];
answer ← Printing.GetPrinterStatus[h];
CrRPC.DestroyClientHandle[h];
};
GetPrintRequestStatus: PUBLIC PROC [request: PrintRequest] RETURNS [status: RequestStatus] ~ {
addr: XNS.Address; h: CrRPC.Handle; service: CHName.Name;
realStatus: Printing.RequestStatus;
[service, addr] ← XNSCH.LookupAddressFromRope[request.context.printerName];
addr.socket ← XNS.unknownSocket; -- Kluge for CH bug
h ← CrRPC.CreateClientHandle[class~$SPP, remote~addr];
realStatus ← Printing.GetPrintRequestStatus[h, request.requestID];
CrRPC.DestroyClientHandle[h];
FOR i: CARDINAL IN [0..realStatus.length) DO
WITH realStatus.body[i] SELECT FROM
v: status Printing.JobStatus => { status.status ← v.status; };
v: statusMessage Printing.JobStatus => { status.statusMessage ← v.statusMessage; };
ENDCASE => { ERROR };
ENDLOOP;
};
PrintFromFile: PUBLIC PROC [file: ROPE, context: Context, update: StatusChangedProc ← NIL] RETURNS [request: PrintRequest] ~ {
addr: XNS.Address; h: CrRPC.Handle;
s: IO.STREAM;
s ← FS.StreamOpen[file
! FS.Error => IF (error.group # $bug)
THEN { ERROR CommandTool.Failed[FSErrorMsg[error]]; }
];
request ← CreatePrintRequest[context];
request.fileName ← file;
request.ipMasterStream ← s;
[request.distinguishedName, addr] ← XNSCH.LookupAddressFromRope[context.printerName];
addr.socket ← XNS.unknownSocket; -- Kluge for CH bug
h ← CrRPC.CreateClientHandle[class~$SPP, remote~addr, timeoutMsec~XNSStream.waitForever];
h.clientData ← request;
request.requestID ← Printing.Print[h, Xfer, request.attributes, request.options];
CrRPC.DestroyClientHandle[h];
IF (s # NIL) THEN IO.Close[s];
IF (update # NIL) THEN RegisterPrintRequest[request, update];
};
PrintFromStream: PUBLIC PROC [s: IO.STREAM, context: Context, update: StatusChangedProc ← NIL] RETURNS [request: PrintRequest] ~ {
addr: XNS.Address; h: CrRPC.Handle;
request ← CreatePrintRequest[context];
request.ipMasterStream ← s;
[request.distinguishedName, addr] ← XNSCH.LookupAddressFromRope[context.printerName];
addr.socket ← XNS.unknownSocket; -- Kluge for CH bug
h ← CrRPC.CreateClientHandle[class~$SPP, remote~addr];
h.clientData ← request;
request.requestID ← Printing.Print[h, Xfer, request.attributes, request.options];
CrRPC.DestroyClientHandle[h];
IF (update # NIL) THEN RegisterPrintRequest[request, update];
};
Xfer: CrRPC.BulkDataXferProc
[h: Handle, stream: IO.STREAM, checkAbort: BulkDataCheckAbortProc] RETURNS [abort: BOOL]
~ {
bufSize: NAT ~ 1024;
buf: REF TEXT ~ RefText.ObtainScratch[bufSize];
request: PrintRequest ← NARROW [h.clientData];
abort ← FALSE;
DO
IF IO.EndOf[request.ipMasterStream] THEN EXIT;
IF (abort ← checkAbort[h]) THEN EXIT;
[] ← IO.GetBlock[request.ipMasterStream, buf];
IO.PutBlock[stream, buf];
ENDLOOP;
RefText.ReleaseScratch[buf];
};
Context Procs
GetDefaults: PUBLIC PROC [context: Context ← NIL] RETURNS [newContext: Context] ~ {
newContext ← IF (context = NIL) THEN NEW[ContextObject] ELSE context;
newContext.senderName ← UserCredentials.Get[].name;
newContext.message ← UserProfile.Line[BANNER, ""];
newContext.printObjectName ← UserProfile.Line[CFNAME, "No File Name"];
newContext.copyCount ← UserProfile.Number[COPYCOUNT, 1];
newContext.printObjectCreateDate ← BasicTime.ToNSTime[BasicTime.nullGMT];
newContext.printObjectCreateDate ← UserProfile.Line[CREATEDATE, ""];
newContext.printerName ← UserProfile.Line[IPPRINTER, "Huh? -- no printer!"];
newContext.releaseKey ← UserProfile.Number[KEY, 0];
newContext.mediumHint ← UserProfile.Line[MEDIUM, "paper"];
newContext.recipientName ← UserProfile.Line[PIGEONHOLE, newContext.senderName];
newContext.pageFirst ← UserProfile.Number[PAGEFIRST, 1];
newContext.pageLast ← UserProfile.Number[PAGELAST, 177777B];
newContext.printObjectSize ← UserProfile.Number[PRINTSIZE, 0];
newContext.priorityHint ← UserProfile.Line[PRIORITY, "normal"];
newContext.stapled ← UserProfile.Boolean[STAPLED, FALSE];
newContext.twoSided ← UserProfile.Boolean[TWOSIDED, TRUE];
};
CreateAttributes: PUBLIC PROC [context: Context] RETURNS [attributes: Printing.PrintAttributes] ~ {
attributes ← NEW[ Printing.PrintAttributesObject[3] ];
TRUSTED { attributes.body[0] ← [printObjectName[context.printObjectName]] };
TRUSTED { attributes.body[1] ← [printObjectCreateDate[context.printObjectCreateDate]] };
TRUSTED { attributes.body[2] ← [senderName[context.senderName]] };
};
CreateOptions: PUBLIC PROC [context: Context] RETURNS [options: Printing.PrintOptions] ~ {
options ← NEW[ Printing.PrintOptionsObject[5] ];
TRUSTED { options.body[0] ← [recipientName[context.recipientName]] };
TRUSTED { options.body[1] ← [message[context.message]] };
TRUSTED { options.body[2] ← [copyCount[context.copyCount]] };
TRUSTED { options.body[3] ← [staple[context.stapled]] };
TRUSTED { options.body[4] ← [twoSided[context.twoSided]] };
};
CreatePrintRequest: PUBLIC PROC [context: Context] RETURNS [request: PrintRequest] ~ {
privateContext: Context ← NEW [ContextObject ← context^];
request ← NEW[PrintRequestObject];
request.context ← privateContext;
request.update ← NIL;
request.distinguishedName ← [NIL, NIL, NIL];
request.requestID ← ALL[0];
request.lastStatus ← [unknown, "uninitialized lastStatus"];
request.attributes ← CreateAttributes[context];
request.options ← CreateOptions[context];
request.fileName ← context.printObjectName;
request.ipMasterStream ← NIL;
};
NewProfile: UserProfile.ProfileChangedProc ~ {
userContext ← GetDefaults[userContext];
};
NewUser: UserCredentials.CredentialsChangeProc ~ {
userContext ← GetDefaults[userContext];
};
Initialization
Init: ENTRY PROC ~ {
watcherProcess ← CedarProcess.Fork[WatchRequestList];
userContext ← GetDefaults[];
UserProfile.CallWhenProfileChanges[NewProfile];
UserCredentials.RegisterForChange[NewUser];
};
Init[];
}...