// ChatDisBSP.BCPL - Bob Sproull - Stuff requiring BSP definitions // Copyright Xerox Corporation 1979 // modified: April 13, 1979 6:04 PM (E. Taft) get "Chat.d" get "ChatBSP.d" external [ // outgoing procedures ChatDIS; AwaitDisplayConnection // incoming procedures DisReset; DisClose; DisWs CheckShiftSwat; BigStack; SmallStack OpenLevel1Socket; SetAllocation; ReleasePBI OpenRTPSocket; CreateBSPStream CallContextList; Block; InitializeContext SetTimer; TimerHasExpired Enqueue; Unqueue Closes SetBlock GotoLabel // incoming statics TTYStr; TTYSoc; DISStr; DISSoc disTypeInCtx; disTypeOutCtx; disDisplayCtx; disEventCtx DisErrStack; DisErr; DisMarkCount; staticErrCode Running; ChatZone; ConnectionOpen ctxQ lvUserFinishProc ] static [ disSavedUFP ] //Come here with communications going (TTYSoc, TTYStr ok) // ChatZone set up // ScreenBuffer => region for screen +DCB // ScreenBufferLength = length of both let ChatDIS() be [ DisReset() // Set up the various kinds of error handling (too many!) TTYStr>>ST.error=DisHandleBSPError TTYSoc>>BSPSoc.bspOtherPupProc=DisHandlePup disSavedUFP = @lvUserFinishProc @lvUserFinishProc=DisHandleFinish //Now start everything up: Running=1 [ CallContextList(ctxQ!0) CheckShiftSwat() ] repeat ] and AwaitDisplayConnection() be [ if DISStr then Closes(DISStr) DISStr=0 let lclPort=vec lenPort SetBlock(lclPort, 0, lenPort) lclPort>>Port.socket^2=#66 //Socket number #66 OpenLevel1Socket(DISSoc, lclPort) SetAllocation(DISSoc, nDisplayPBI, nDisplayPBI-1, nDisplayPBI-1) until OpenRTPSocket(DISSoc, ctxQ, modeListenAndWait, 0,0,0, ChatZone) do loop DISStr=CreateBSPStream(DISSoc) DISStr>>ST.error=DisHandleBSPError DISSoc>>BSPSoc.bspOtherPupProc=DisHandlePup DisReset() ConnectionOpen=true ] // Various error and finishing code. and DisHandleFinish(code) be [ @lvUserFinishProc=disSavedUFP @#420=0 //Let display finish during networking let tim=nil SetTimer(lv tim, 3000) // Thirty seconds if Running then Running=2 //Flag to stop everything Unqueue(ctxQ, disTypeInCtx) Unqueue(ctxQ, disTypeOutCtx) Unqueue(ctxQ, disDisplayCtx) Unqueue(ctxQ, disEventCtx) Enqueue(ctxQ, InitializeContext(disEventCtx, 200, DisClose)) until Running eq 0 % TimerHasExpired(lv tim) do CallContextList(ctxQ!0) ] // Stream Errors: simply arrange to return a flag value that indicates // what has happened: // -1: Mark // -2: Interrupt (not yet implementable!) // -3: Grounds for closing connection (bad state) and DisHandleBSPError(str, ec) = valof [ staticErrCode=valof [ switchon ec into [ case ecMarkEncountered: resultis -1 default: //Bad status -- connection to close Block() //Give other guy chance to run resultis -3 ] ] if str eq DISStr then GotoLabel(DisErrStack, DisErr) resultis staticErrCode ] //Called when an error, interrupt, or abort pup is received, and handed // the very pup. and DisHandlePup(PBI) be [CPE if PBI>>PBI.pup.type eq typeError then [ let C=lv PBI>>PBI.pup.bytes let sl=PBI>>PBI.pup.length+(-22-24+1) //Text length+1 let fp=C+11 @fp=(sl lshift 8)+#40 //Length,,space fp=BigStack(fp) DisWs("*n*l") DisWs(fp) //Print message if any DisWs(" [Error PUP]*n*l") SmallStack() if C!10 eq 2 then //The only fatal one for now. [ finish //No point in continuing. ] ] // Should really check socket, but not easy.... if PBI>>PBI.pup.type eq typeInterrupt then [ DisMarkCount=DisMarkCount+1 //Grumble..... ] ReleasePBI(PBI) ]CPE