Syntax10.Scn.Fnt Syntax10i.Scn.Fnt StampElems Alloc 28 Feb 96 Syntax10b.Scn.Fnt MODULE Terminal; (* ww IMPORT TerminalFrames, Terminals, Sessions, Oberon, MenuViewers, Viewers, TextFrames, Texts, Fonts, Display, Files; CONST DefaultMenu = "System.Close System.Copy System.Grow Terminal.Reset Terminal.Stop "; TYPE Text = POINTER TO TextDesc; Terminal* = POINTER TO TerminalDesc; TerminalDesc = RECORD(Sessions.TerminalDesc) text: Text; state: INTEGER END; TextDesc = RECORD(Terminals.TerminalDesc) term: Terminal END; w: Texts.Writer; PROCEDURE Receive(t: Sessions.Terminal; ch: CHAR); BEGIN Terminals.Receive(t(Terminal).text, ch) END Receive; PROCEDURE TelnetInitReceiver(t: Sessions.Terminal; ch: CHAR); VAR s: Sessions.Session; BEGIN WITH t: Terminal DO IF t.state = 1 THEN IF ch = 0FFX THEN t.state := 2 ELSE t.receive := Receive; Receive(t, ch) END ELSIF t.state = 2 THEN IF ch = 0FDX THEN t.state := 4 ELSIF ch > 0FAX THEN t.state := 3 ELSE t.state := 1 END ELSIF t.state = 3 THEN t.state := 1 ELSIF t.state = 4 THEN IF ch = 18X THEN s := Sessions.ThisSession(t); Sessions.SendChar(s, 0FFX); Sessions.SendChar(s, 0FCX); Sessions.SendChar(s, 18X) END; t.state := 1 ELSE t.state := 1 END END END TelnetInitReceiver; PROCEDURE Flush(t: Sessions.Terminal; changed, terminated: BOOLEAN); BEGIN Terminals.Flush(t(Terminal).text); IF terminated THEN Sessions.Remove(t) END END Flush; PROCEDURE Send(t: Terminals.Terminal; ch: CHAR); VAR s: Sessions.Session; BEGIN s := Sessions.ThisSession(t(Text).term); IF s # NIL THEN Sessions.SendChar(s, ch) END END Send; PROCEDURE Break(t: Terminals.Terminal); VAR s: Sessions.Session; BEGIN s := Sessions.ThisSession(t(Text).term); IF s # NIL THEN Sessions.SendBreak(s) END END Break; PROCEDURE IsTerminal(t: Sessions.Terminal): BOOLEAN; BEGIN RETURN t IS Terminal END IsTerminal; PROCEDURE New*(s: Sessions.Session): Terminal; VAR t: Terminal; text: Text; BEGIN NEW(t); NEW(text); t.text := text; text.term := t; t.state := 1; Terminals.Open(text, NIL, Send, Break, TerminalFrames.NotifyDisplay); Sessions.Install(t, s, TelnetInitReceiver, Flush, -1); RETURN t END New; PROCEDURE HandleFrame*(f: Display.Frame; VAR m: Display.FrameMsg); BEGIN IF m IS Sessions.IdentifyMsg THEN m(Sessions.IdentifyMsg).session := Sessions.ThisSession(f(TerminalFrames.Frame).text(Text).term) ELSE TerminalFrames.Handle(f, m) END END HandleFrame; PROCEDURE OpenViewer*(t: Terminal; fnt: Fonts.Font); VAR x, y: INTEGER; v: Viewers.Viewer; mf: TextFrames.Frame; cf: TerminalFrames.Frame; name: ARRAY 64 OF CHAR; BEGIN Sessions.GetName(Sessions.ThisSession(t), name); mf := TextFrames.NewMenu(name, DefaultMenu); IF Files.Old("Terminal.Menu.Text") # NIL THEN Texts.Open(mf.text, "Terminal.Menu.Text"); Texts.WriteString(w, name); Texts.WriteString(w, " | "); Texts.Insert(mf.text, 0, w.buf) END; NEW(cf); TerminalFrames.Open(cf, HandleFrame, t.text, fnt); Oberon.AllocateUserViewer(Oberon.Mouse.X, x, y); v := MenuViewers.New(mf, cf, TextFrames.menuH, x, y) END OpenViewer; PROCEDURE Reset*; VAR v: Viewers.Viewer; f: Display.Frame; BEGIN f := NIL; IF Oberon.Par.vwr.dsc = Oberon.Par.frame THEN f := Oberon.Par.frame.next ELSE v := Oberon.MarkedViewer(); IF v.dsc # NIL THEN f := v.dsc.next END END; IF (f # NIL) & (f IS TerminalFrames.Frame) THEN Terminals.Reset(f(TerminalFrames.Frame).text) END END Reset; PROCEDURE Stop*; VAR v: Viewers.Viewer; f: Display.Frame; term: Terminal; s: Sessions.Session; BEGIN f := NIL; IF Oberon.Par.vwr.dsc = Oberon.Par.frame THEN f := Oberon.Par.frame.next ELSE v := Oberon.MarkedViewer(); IF v.dsc # NIL THEN f := v.dsc.next END END; IF (f # NIL) & (f IS TerminalFrames.Frame) THEN term := f(TerminalFrames.Frame).text(Text).term; s := Sessions.ThisSession(term); IF s # NIL THEN Sessions.Remove(term) END ELSE Texts.WriteString(w, "Terminal.Stop failed (bad receiver)"); Texts.WriteLn(w);Texts.Append(Oberon.Log, w.buf) END END Stop; PROCEDURE Open*; VAR beg, end, time: LONGINT; v: Viewers.Viewer; text: Texts.Text; t: Sessions.Terminal; term: Terminal; fnt: Fonts.Font; s: Texts.Scanner; msg: Sessions.IdentifyMsg; host: ARRAY 32 OF CHAR; BEGIN Texts.OpenScanner(s, Oberon.Par.text, Oberon.Par.pos); Texts.Scan(s); IF (s.class = Texts.Char) & (s.line = 0) & (s.c = "^") THEN Oberon.GetSelection(text, beg, end, time); IF time > 0 THEN Texts.OpenScanner(s, text, beg); Texts.Scan(s) END END; msg.session := NIL; IF (s.line = 0) & (s.class = Texts.Char) & (s.c = "*") THEN v := Oberon.MarkedViewer(); v.handle(v, msg); Texts.Scan(s) ELSE IF (s.line = 0) & ((s.class = Texts.Name) OR (s.class = Texts.String)) THEN COPY(s.s, host); Texts.Scan(s); IF (s.line = 0) & (s.class = Texts.Int) THEN msg.session := Sessions.New(host, s.i); Texts.Scan(s) ELSE msg.session := Sessions.New(host, 23) END END END; IF msg.session # NIL THEN t := Sessions.ThisTerminal(msg.session, IsTerminal); IF t # NIL THEN term := t(Terminal) ELSE term := New(msg.session) END; IF (s.line = 0) & (s.class = Texts.Name) THEN fnt := Fonts.This(s.s); IF fnt.name # s.s THEN fnt := Fonts.This("Courier10.Scn.Fnt") END ELSE fnt := Fonts.This("Courier10.Scn.Fnt") END; OpenViewer(term, fnt) END END Open; BEGIN Texts.OpenWriter(w) END Terminal.