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; 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"; pendingPrintRequests: PrintRequestList _ NIL; userContext: Context; watcherProcess: CedarProcess.Process; 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; }; WaitTilListChanged: ENTRY PROC ~ { WAIT ListChanged; }; WatchRequestList: CedarProcess.ForkableProc ~ { DO WaitTilListChanged[]; ENDLOOP; }; 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 ]; 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 ~ { 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]; }; 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.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]; }; Init: ENTRY PROC ~ { watcherProcess _ CedarProcess.Fork[WatchRequestList]; userContext _ GetDefaults[]; UserProfile.CallWhenProfileChanges[NewProfile]; UserCredentials.RegisterForChange[NewUser]; }; Init[]; }... jXNSPrintRequestManagerImpl.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 UserProfile Tags Global State (atomically altered under the monitor) Request Manager Procs Watcher process Print Service Interaction ! FS.Error => IF (error.group # $bug) THEN { ERROR CommandTool.Failed[FSErrorMsg[error]]; } [h: Handle, stream: IO.STREAM, checkAbort: BulkDataCheckAbortProc] RETURNS [abort: BOOL] Context Procs newContext.printObjectCreateDate _ UserProfile.Line[CREATEDATE, ""]; Initialization Κ E˜šœ™IcodešœH™HKšœ1™1K™$—J™šΟk ˜ Kšœ œœ˜)Kšœ œ˜1Kšœ œ˜KšœœE˜PKšœœ˜Kšœœ$œ˜4Kšœœ!˜.Kšœœœ˜Kšœœ1˜FKšœ œE˜VKšœœ˜#Kšœœ˜$Kšœ œ˜Kšœ ˜ Kšœ˜—K˜šΟnœœ˜)Kšœ!œœ7˜jKšœ˜"Kšœžœžœ'˜H—K˜Kšœœœ˜K˜šœ™K˜KšΠbkœœΟbœ œ˜!KšŸœœ œ œ˜!KšŸ œœ œ  œ˜'KšŸ œœ œ  œ˜)KšŸ œœ œ˜/KšŸœœ œ œ˜KšŸœœ œ œ˜!KšŸ œœ œ  œ˜)KšŸ œœ œ  œ˜'KšŸœœ œ œ˜%KšŸ œœ œ  œ˜'KšŸœœ œ œ˜%KšŸœœ œ œ˜#KšŸœœ œ œ˜%K™—™3K™Kšœ)œ˜-Kšœ˜Kšœ%˜%K˜—™K™Kšž œœ œ˜K˜š žœœœœ5œ˜dKšœœ ˜;Kšœ ˜Kšœ˜K˜—šžœœœœ˜Ešœœ˜šœœ˜!Kšœ˜Kšœ˜—šœ+˜+Kšœ1˜1Kšœ˜—šœ˜ šœ:œœ˜Wšœœ˜%Kšœ˜Kšœ˜Kšœ˜—Kšœ˜Kšœ˜———Kšœ ˜Kšœ˜K˜—š žœœœœœ˜KKšœ˜Kšœ˜—K™—™K˜šžœœœ˜"Kšœ ˜Kšœ˜K˜—šžœ˜/šœ˜Kšœ˜Kšœ˜—Kšœ˜—K™—™K™š žœœœ œœ?˜xKšœœ˜#Kšœœ ˜7KšœœΟc˜4Kšœ6˜6Kšœ*˜*Kšœ˜K˜K˜—š žœœœ œœ;˜pKšœœ˜#Kšœœ ˜7Kšœœ‘˜4Kšœ6˜6Kšœ&˜&Kšœ˜˜K˜——šžœœœœ˜^Kšœœ0˜9Kšœ#˜#Kšœœ4˜KKšœœ‘˜4Kšœ6˜6KšœB˜BKšœ˜šœœœ˜,šœœ˜#Jšœ>˜>JšœS˜SJšœœ˜—Jšœ˜—Kšœ˜K˜—š ž œœœœ0œœ˜~Kšœœ˜#Kšœœœ˜ šœœ˜šœœ œ™%Kšœœ)™5—Kšœ˜—Kšœ&˜&Kšœ˜Kšœ˜Kšœ$œ,˜UKšœœ‘˜4KšœY˜YKšœ˜KšœQ˜QKšœ˜Kšœœœœ ˜Kšœ œœ'˜=K˜K˜—šžœœœœœ0œœ˜‚Kšœœ˜#Kšœ&˜&Kšœ˜Kšœ$œ,˜UKšœœ‘˜4Kšœ6˜6Kšœ˜KšœQ˜QKšœ˜Kšœ œœ'˜=K˜K˜—šžœ˜Kš œœœ&œ œ™XK˜Kšœ œ˜Kšœœœ"˜/Kšœœ˜.Kšœœ˜š˜Kšœœœœ˜.Kšœœœ˜%Kšœœ'˜.Kšœ˜Kšœ˜—Kšœ˜K˜—K˜—šœ ™ K˜š ž œœœœœ˜SKš œ œ œœœœ ˜EKšœ3˜3Kšœ&Ÿœ˜2Kšœ.Ÿœ˜FKšœ*Ÿ œ˜8KšœI˜IKšœ4Ÿ œ™DKšœ*Ÿ œ˜LKšœ+Ÿœ˜3Kšœ)Ÿœ ˜:Kšœ,Ÿ œ˜OKšœ*Ÿ œ˜8Kšœ)Ÿœ ˜Kšœ+Ÿœ ˜?Kšœ)Ÿœœ˜9Kšœ*Ÿœœ˜:K˜K˜—šžœœœœ+˜cKšœ œ&˜6KšœE˜LKšœQ˜XKšœ;˜BK˜K˜—šž œœœœ%˜ZKšœ œ#˜0Kšœ>˜EKšœ2˜9Kšœ6˜=Kšœ1˜8Kšœ4˜;K˜K˜—šžœœœœ˜VKšœœ˜9Kšœ œ˜"Kšœ!˜!Kšœœ˜Kšœœœœ˜,Kšœœ˜Kšœ;˜;Kšœ/˜/Kšœ)˜)Kšœ+˜+Kšœœ˜K˜K˜—šž œ$˜.Kšœ'˜'Kšœ˜K˜—šžœ+˜2Kšœ'˜'Kšœ˜—K˜—šœ™K˜šžœœœ˜Kšœ5˜5Kšœ˜Kšœ/˜/Kšœ+˜+K˜——K˜K˜K˜Kšœ˜K˜J™—…—!Έ.g