DIRECTORY Args, Ascii, Basics, CharDisplays, Commander, DisplayControllers, EditedStream, FileNames, IO, PlumbCommandsCommon, Plumber, Process, Rope, TermProgs, TiogaOps, TIPLinking, TIPTableAccess, TIPTypes, TIPUser, TypeScript, UnixFileDescriptorStream, UnixTypes, ViewerClasses, ViewerEvents, ViewerIO, ViewerOps; PlumbCommandsCommonImpl: CEDAR PROGRAM IMPORTS Args, Basics, CharDisplays, DisplayControllers, EditedStream, FileNames, IO, Plumber, Process, Rope, TermProgs, TiogaOps, TIPLinking, TIPTableAccess, TIPUser, TypeScript, UnixFileDescriptorStream, ViewerEvents, ViewerIO, ViewerOps EXPORTS PlumbCommandsCommon ~ { TIPTable: TYPE ~ TIPTypes.TIPTable; myTipTableFile: Rope.ROPE ฌ Rope.Concat[FileNames.CurrentWorkingDirectory[], "Plumber.tip"]; PlumbAndTermCommand: PUBLIC PROC [cmd: Commander.Handle, termCommand: BOOLEAN] RETURNS [result: REF, msg: Rope.ROPE] ~ { execP, ttyP, waitP, termP, debugP: BOOLEAN; todo, termName: Rope.ROPE; execArg, ttyArg, waitArg, termArg, debugArg, commandArg: Args.Arg; [execArg, ttyArg, waitArg, debugArg, termArg, commandArg] ฌ Args.ArgsGet[ cmd: cmd, format: "-E%b-T%b-W%b-D%b-term%s[s" ! Args.Error => { msg ฌ Rope.Concat["Badly formed arguments: ", reason]; GO TO argsError }; ]; termP ฌ termArg.ok; termName ฌ IF termArg.ok THEN termArg.rope ELSE "sun"; execP ฌ execArg.ok; ttyP ฌ ttyArg.ok; waitP ฌ waitArg.ok; debugP ฌ debugArg.ok; IF commandArg.ok THEN { todo ฌ commandArg.rope; } ELSE { IF termCommand THEN { todo ฌ Rope.Concat["LocalShell -f TERM=", termName]; execP ฌ TRUE; ttyP ฌ TRUE; } ELSE { todo ฌ "LocalShell"; execP ฌ TRUE; ttyP ฌ TRUE; } }; IF termCommand THEN RETURN DoTermCommand[ cmd, execP, ttyP, waitP, termP, debugP, todo, termName ] ELSE RETURN DoPlumbCommand[ cmd, execP, ttyP, waitP, termP, debugP, todo, termName ]; EXITS argsError => RETURN [result: $Failure, msg: msg]; }; DoTermCommand: PROC [cmd: Commander.Handle, execP, ttyP, waitP, termP, debugP: BOOLEAN, todo, termName: Rope.ROPE] RETURNS [result: REF, msg: Rope.ROPE] ~ { IF ~ Basics.IsBound[TermProgs.GetTerm] THEN RETURN [result: $Failure, msg: "Terminal Emulator not loaded."]; { term: TermProgs.Term ~ TermProgs.GetTerm[name: termName, cmd: cmd]; charDisplay: CharDisplays.CharDisplay; displayController: DisplayControllers.DisplayController; driverStream: IO.STREAM ฌ UnixFileDescriptorStream.Create[ ]; IF term = NIL THEN RETURN [result: $Failure, msg: "Couldn't load terminal requested."]; charDisplay ฌ CharDisplays.Create[ class: CharDisplays.GetClass["Simple"], -- Formerly "UnselectedFlushedBufferedTioga" client: NEW [CharDisplays.ClientRep ฌ [InitiateChangeDetails, driverStream]], name: IO.PutFR[ "%g (%g)", IO.rope[todo], IO.rope[termName] ], tipTableName: term.tipTableName, det: term.det, initData: driverStream ]; IF ~ execP THEN todo ฌ IO.PutFR["TERM=%g %g", IO.rope[termName], IO.rope[todo] ]; displayController ฌ DisplayControllers.Create[ cd: charDisplay, cp: term.cp]; DisplayControllers.SetDriver[ displayController, driverStream ]; IF waitP THEN TRUSTED { [] ฌ SwimUpstream[ viewer: charDisplay.viewer, toViewer: displayController.toDisplay, fromViewer: displayController.fromDisplay, command: todo, exec: execP, tty: ttyP, debug: debugP, driverStream: driverStream] } ELSE Process.Detach[FORK SwimUpstream[ viewer: charDisplay.viewer, toViewer: displayController.toDisplay, fromViewer: displayController.fromDisplay, command: todo, exec: execP, tty: ttyP, debug: debugP, driverStream: driverStream] ]; RETURN [result: NIL, msg: NIL] } }; InitiateChangeDetails: PROC [c: CharDisplays.Client, cd: CharDisplays.CharDisplay, new: CharDisplays.DisplayDetails] RETURNS [BOOL] ~ { driverStream: IO.STREAM ~ NARROW[c.clientData]; cd.class.ChangeDetails[cd, new]; UnixFileDescriptorStream.SetTerminalSize[ driverStream, cd.det.lines, cd.det.columns ]; RETURN [TRUE]}; DoPlumbCommand: PROC [cmd: Commander.Handle, execP, ttyP, waitP, termP, debugP: BOOLEAN, todo, termName: Rope.ROPE] RETURNS [result: REF, msg: Rope.ROPE] ~ { IF termP THEN RETURN[result: $Failure, msg: "Use the 'term' command"] ELSE { toTypescript, fromTypescript: IO.STREAM; plumbTipTable: TIPUser.TIPTable ฌ NIL; typescript: TypeScript.TS ~ TypeScript.Create[info: [name: todo, column: right, iconic: TRUE]]; plumbTipTable ฌ TIPUser.InstantiateNewTIPTable[myTipTableFile ! TIPUser.InvalidTable => CONTINUE]; IF plumbTipTable # NIL THEN { TIPTableAccess.SetMouseTicks[plumbTipTable, MIN[TIPTableAccess.GetMouseTicks[plumbTipTable], TIPTableAccess.GetMouseTicks[typescript.tipTable]] ]; TIPTableAccess.SetOpaque[plumbTipTable, FALSE]; [] ฌ TIPLinking.Append[early: plumbTipTable, late: typescript.tipTable]; typescript.tipTable ฌ plumbTipTable; }; TiogaOps.SetNodeStyle[style: "ascii", node: TiogaOps.ViewerDoc[viewer: typescript]]; [in: fromTypescript, out: toTypescript] ฌ ViewerIO.CreateViewerStreams[ name: todo, viewer: typescript, editedStream: FALSE]; EditedStream.SetEcho[self: fromTypescript, echoTo: NIL]; toTypescript ฌ PlumberTypescriptCreate[out: toTypescript ]; IF waitP THEN TRUSTED { [] ฌ SwimUpstream[ viewer: typescript, toViewer: toTypescript, fromViewer: fromTypescript, command: todo, exec: execP, tty: ttyP, debug: debugP, driverStream: NIL ] } ELSE Process.Detach[FORK SwimUpstream[ viewer: typescript, toViewer: toTypescript, fromViewer: fromTypescript, command: todo, exec: execP, tty: ttyP, debug: debugP, driverStream: NIL ] ]; RETURN [result: NIL, msg: NIL] } }; ConduitWrapper: TYPE = REF ConduitWrapperRep; ConduitWrapperRep: TYPE = RECORD [ conduit: Plumber.Conduit ]; DestroyPlumberViewer: ViewerEvents.EventProc ~ { wrapper: ConduitWrapper ฌ NARROW[ViewerOps.FetchProp[viewer: viewer, prop: $PlumberConduit]]; IF event # destroy OR before # TRUE THEN ERROR; Process.Detach[ FORK Plumber.Terminate[wrapper.conduit, $Normal] ]; RETURN [abort: FALSE]; }; SwimUpstream: PROCEDURE [ viewer: ViewerClasses.Viewer, toViewer: IO.STREAM, fromViewer: IO.STREAM, command: Rope.ROPE, exec,tty,debug: BOOLEAN, driverStream: IO.STREAM] RETURNS [] ~ { wd: Rope.ROPE ~ FileNames.CurrentWorkingDirectory[]; conduit: Plumber.Conduit ~ Plumber.MakeConduit[ stdin:fromViewer, stdout:toViewer, stderr:toViewer, debug:debug, noisy: TRUE ]; RecordSourceFD: PROC [fd: UnixTypes.FileDescriptor] ~ { IF driverStream # NIL THEN UnixFileDescriptorStream.SetFD[ driverStream, fd ]; }; WHILE viewer.menu = NIL AND viewer.parent # NIL DO viewer ฌ viewer.parent ENDLOOP; ViewerOps.AddProp[viewer: viewer, prop: $PlumberConduit, val: NEW[ConduitWrapperRep ฌ [conduit: conduit]]]; [] ฌ ViewerEvents.RegisterEventProc[proc: DestroyPlumberViewer, event: ViewerEvents.ViewerEvent.destroy, filter: viewer, before: TRUE]; viewer.guardDestroy ฌ TRUE; [] ฌ Plumber.SpawnWithConduit[ conduit: conduit, command: command, wd: wd, exec: exec, tty: tty, reportSourceFD: RecordSourceFD ]; viewer.guardDestroy ฌ FALSE; RETURN; }; PlumberTypescriptStateRep: TYPE = RECORD [ out: IO.STREAM, viewer: ViewerClasses.Viewer ]; PlumberTypescriptState: TYPE = REF PlumberTypescriptStateRep; PlumberTypescriptCreate: PROC [out: IO.STREAM] RETURNS [IO.STREAM] ~ { s: PlumberTypescriptState; v: ViewerClasses.Viewer ฌ ViewerIO.GetViewerFromStream[stream: out]; IF NOT TypeScript.IsATypeScript[ts: v] THEN ERROR; s ฌ NEW [ PlumberTypescriptStateRep ฌ [ out: out, viewer: v ] ]; RETURN [IO.CreateStream[PlumberTypescriptProcs, s]]; }; PlumberTypescriptPutChar: PROC [self: IO.STREAM, char: CHAR] ~ { s: PlumberTypescriptState = NARROW[self.streamData]; SELECT char FROM Ascii.BEL => ViewerOps.BlinkViewer[viewer: s.viewer, milliseconds: 50]; Ascii.BS => TypeScript.BackSpace[ts: s.viewer]; Ascii.TAB, Ascii.LF, IN [Ascii.SP..0176C] => IO.PutChar[s.out, char]; ENDCASE => NULL; }; PlumberTypescriptPutBlock: PROC [self: IO.STREAM, block: REF READONLY TEXT, startIndex: NAT ฌ 0, count: NAT ฌ NAT.LAST] ~ { s: PlumberTypescriptState = NARROW[self.streamData]; haveSpecial: BOOLEAN ฌ FALSE; IF startIndex+count > block.maxLength THEN count ฌ block.length - startIndex; FOR i: INT IN [startIndex..startIndex+count) DO char: CHAR ฌ block[i]; haveSpecial ฌ NOT ((char IN [Ascii.SP..0176C]) OR (char=Ascii.TAB) OR (char=Ascii.LF)); IF haveSpecial THEN EXIT; ENDLOOP; IF haveSpecial THEN FOR i: INT IN [startIndex..startIndex+count) DO PlumberTypescriptPutChar[ self, block[i] ] ENDLOOP ELSE IO.PutBlock[self: s.out, block: block, startIndex: startIndex, count: count]; }; PlumberTypescriptProcs: REF IO.StreamProcs = IO.CreateStreamProcs [ variety: $output, class: $PlumberTypescriptOutput, putBlock: PlumberTypescriptPutBlock, putChar: PlumberTypescriptPutChar ]; }. ๎ PlumbCommandsCommonImpl.mesa Copyright ำ 1989, 1992 by Xerox Corporation. All rights reserved. Peter B. Kessler, May 15, 1990 3:23 pm PDT Norman Adams, June 8, 1990 2:17 pm PDT. Spreitze, April 3, 1990 2:00 pm PDT Brent Welch March 7, 1991 4:05 pm PST Willie-s, June 16, 1992 4:59 pm PDT Bier, March 11, 1993 6:10 pm PST -- didn't get a command so use LocalShell, set execP and ttyP as LocalShell needs -- fill in the file descriptor when we get it back from plumber name: todo, RETURN DoTermCommand[ cmd, execP, ttyP, waitP, termP, todo, termName ] layer Plumber.tip on top of the typescript. plumbTipTable.mouseTicks ฌ MIN[ plumbTipTable.mouseTicks, typescript.tipTable.mouseTicks]; plumbTipTable.opaque ฌ FALSE; Only here because "discrimination on opaque types is unimplemented" PROC [viewer: Viewer, event: ViewerEvent, before: BOOL] RETURNS [abort: BOOL _ FALSE] Plumber TypeScript output streams IF haveSpecial THEN MessageWindow.Append["|",FALSE] ELSE MessageWindow.Append[".",FALSE]; ส ม•NewlineDelimiter –(cedarcode) style™code™Kšœ ะerœ7™BK™*K™(K™#K™%K™#K™ J™—šฯk ˜ –0 bp restIndentšœ[žœฒžœ"˜ฒK˜——šฯnœžœžœ˜'šžœ˜K–0 bp restIndentšœIžœ›˜ๆ—–0 bp restIndentšž˜K–0 bp restIndent˜—K˜K˜Kšœ žœ˜#KšœžœC˜\K˜KšŸœž œ&žœ˜Ošžœ žœ žœ˜)K˜Kšœ#žœ˜,Kšœžœ˜K˜K˜BK˜˜<˜;šœ˜K˜7Kšžœžœ ˜Kšœ˜—K˜—K˜—K˜Kšœ žœ žœžœ˜6K˜K˜K˜K˜K˜šžœžœ˜K˜—šœžœ˜KšœQ™Qšžœ žœ˜K˜4Kšœžœ˜ Kšœžœ˜ —šœžœ˜K˜Kšœžœ˜ Kšœžœ˜ K˜—K˜K˜—K˜šžœ žœ˜KšžœH˜N—šž˜KšžœJ˜P—K˜šžœžœ˜7K˜—K˜K˜K˜—šŸ œžœ<žœžœžœ žœ žœ˜œK˜šžœ%žœ˜,Kšžœ:˜@K˜—Kšœ˜˜KšœC˜CKšœ&˜&Kšœ8˜8K˜Kšœ?™?Kšœžœžœ'˜>Kšœ˜Kšžœ žœžœžœ>˜XK˜˜"Kšœ(ฯc,˜TKšœžœB˜MKšœžœžœ žœ˜>Kšœ ™ Kšœ!˜!Kšœ˜K˜Kšœ˜K˜—šžœ žœ˜Kšœžœžœžœ˜AK˜—K˜MK˜Kšœ@˜@K˜šžœžœžœ˜K˜า—šœž˜Kšœžœั˜ไ—K˜Kšžœ žœžœ˜K˜—K˜K˜—šŸœžœZžœžœ˜‡Kšœžœžœžœ˜/Kšœ ˜ KšœW˜WKšžœžœ˜—K˜KšŸœžœ<žœžœžœ žœ žœ˜˜Kšžœž˜ ˜Kšžœ@™FKšžœ1˜7K˜—Kšžœ˜˜Kšœžœžœ˜(Kšœ"žœ˜&šœžœ˜Kšœ<žœ˜C—K˜K™+˜=Kšœžœ˜$—šžœžœžœ˜šœžœ™Kšœ:™:—˜+šžœ-˜0K˜5——Kšœžœ™Kšœ(žœ˜/K˜HK˜$K˜K˜—K˜TK˜˜GKšœ.žœ˜5K˜—Kšœ3žœ˜8K˜K˜;K˜šžœžœžœ˜KšœŸžœ˜ค—šœž˜Kšœžœ›žœ˜ท—Kšžœ žœžœ˜K˜K˜K˜—K˜K˜—K™CKšœžœžœ˜-šœžœžœ˜>K˜—šŸœ˜0Kš žœ.žœžœ žœžœ™UKšœžœ=˜]Kš žœžœ žœžœžœ˜/Kšœžœ/˜CKšžœ žœ˜Kšœ˜K˜K˜—šŸ œž œ+žœžœžœžœžœžœžœžœžœ˜บK˜Kšœ žœ'˜4K˜šœ0˜0KšœHž˜LKšœ˜K˜—šŸœžœ#˜7Kšžœžœžœ4˜NK˜—K˜š žœžœžœžœžœžœ˜RK˜—šœ>žœ*˜kK˜—Kšœžœ˜‡K˜K˜Kšœžœ˜K˜K˜‚K˜Kšœžœ˜Kšžœ˜K˜K˜——šะbl"™"K˜šœžœžœ˜*Kšœžœžœ˜K˜Kšœ˜—Kšœžœžœ˜=K˜šŸœžœžœžœžœžœžœ˜FKšฯbœ˜K˜DKšžœžœ!ž œ˜2K˜Kšขœžœ:˜AKšžœžœ&ขœ˜4K˜K˜—K˜šŸœžœž œžœ˜@Kšขœžœ˜4šžœž˜Kšœžœ"ขœ˜GKšœžœขœ ˜/Kš œžœžœžœžœ žœ ขœ ˜EKšžœžœ˜—K˜K˜—šŸœžœž œ žœžœžœžœ žœžœ˜{Kšขœžœ˜4—˜Kšœ žœžœ˜K˜Kšžœ$žœ#˜MK˜šžœžœžœ žœ˜0Kšœžœ ˜Kšœžœžœžœ žœ žœžœ žœ˜WKšžœ žœžœ˜Kšžœ˜K˜—šžœ žœ™K™—šž™K™ —K˜šžœ žœ˜šžœžœžœ žœ˜0Kšœ*˜*Kšž˜——šžœ˜Kšžœขœ:˜M—K˜—K˜šœžœžœžœ˜CK˜Kšœ ˜ Kšœ$˜$Kšœ!˜!K˜K˜—K˜K˜——…—!ศ/w