Oberon/A2/Oberon.Configuration.Mod

(* ETH Oberon, Copyright 2001 ETH Zuerich Institut fuer Computersysteme, ETH Zentrum, CH-8092 Zuerich. Refer to the "General ETH Oberon System Source License" contract available at&#58; http&#58;//www.oberon.ethz.ch/ *) MODULE Configuration IN Oberon;	(** portable *)	(* jm, Configuration module/code borrowed from ET by uh **) (* &#9;contains a lot of code borrowed from ET &#42;) IMPORT Modules, Display, Input, Viewers, Texts, Oberon; CONST &#9;CR &#61; 0DX; &#9;Default &#61; "Configuration.Text"; VAR &#9;W&#58; Texts.Writer; &#9;sX, sY&#58; INTEGER;	(* saved coordinates for newm viewer &#91;used in Marker &#93; *) PROCEDURE OpenScanner(VAR S&#58; Texts.Scanner); &#9;VAR &#9;&#9;text&#58; Texts.Text; &#9;&#9;beg, end, time&#58; LONGINT; BEGIN &#9;Texts.OpenScanner(S, Oberon.Par.text, Oberon.Par.pos); &#9;Texts.Scan(S); &#9;IF (S.class &#61; Texts.Char) &#38; (S.c &#61; "^") THEN &#9;&#9;text &#58;&#61; NIL; time &#58;&#61; 0; Oberon.GetSelection(text, beg, end, time); &#9;&#9;IF (text &#61; NIL) OR (time &#60;&#61; 0) THEN S.class &#58;&#61; Texts.Inval; RETURN END; &#9;&#9;Texts.OpenScanner(S, text, beg); Texts.Scan(S) &#9;END END OpenScanner; (** Execute commands contained in the text. Each command must be on a separate line. *) PROCEDURE do*(T&#58; Texts.Text; beg, end&#58; LONGINT); VAR S&#58; Texts.Scanner; pos&#58; LONGINT; res&#58; INTEGER; &#9;PROCEDURE NextCmd; &#9;&#9;VAR tR&#58; Texts.Reader; ch&#58; CHAR; &#9;BEGIN &#9;&#9;IF pos &#60; end THEN &#9;&#9;&#9;Texts.OpenReader(tR, T, pos); Texts.Read(tR, ch); &#9;&#9;&#9;LOOP &#9;&#9;&#9;&#9;WHILE &#126;tR.eot &#38; (ch # CR) DO Texts.Read(tR, ch) END; &#9;&#9;&#9;&#9;Texts.Read(tR, ch); &#9;&#9;&#9;&#9;IF tR.eot THEN &#9;&#9;&#9;&#9;&#9;EXIT &#9;&#9;&#9;&#9;ELSIF (ch &#62; " ") &#38; (ch # "!") &#38; (ch # "#") THEN &#9;&#9;&#9;&#9;&#9;pos &#58;&#61; Texts.Pos(tR)-1; &#9;&#9;&#9;&#9;&#9;Texts.OpenScanner(S, T, pos); Texts.Scan(S); &#9;&#9;&#9;&#9;&#9;RETURN &#9;&#9;&#9;&#9;END &#9;&#9;&#9;END &#9;&#9;END; &#9;&#9;S.class &#58;&#61; Texts.Inval &#9;END NextCmd; &#9;PROCEDURE FirstCmd; &#9;&#9;VAR tR&#58; Texts.Reader; ch&#58; CHAR; &#9;BEGIN &#9;&#9;IF pos &#60; end THEN &#9;&#9;&#9;Texts.OpenReader(tR, T, pos); Texts.Read(tR, ch); &#9;&#9;&#9;IF &#126;tR.eot &#38; (ch &#62; " ") &#38; (ch # "!") &#38; (ch # "#") THEN &#9;&#9;&#9;&#9;pos &#58;&#61; Texts.Pos(tR)-1; &#9;&#9;&#9;&#9;Texts.OpenScanner(S, T, pos); Texts.Scan(S); &#9;&#9;&#9;&#9;RETURN &#9;&#9;&#9;END &#9;&#9;END; &#9;&#9;NextCmd &#9;END FirstCmd; &#9;PROCEDURE UserInterrupt&#58; BOOLEAN; &#9;VAR ch&#58; CHAR; &#9;BEGIN &#9;&#9;WHILE Input.Available # 0 DO &#9;&#9;&#9;Input.Read(ch); &#9;&#9;&#9;IF ch &#61; CHR(27) THEN RETURN TRUE END &#9;&#9;END; &#9;&#9;RETURN FALSE &#9;END UserInterrupt; BEGIN &#9;pos &#58;&#61; beg; FirstCmd; &#9;WHILE (S.class &#61; Texts.Name) &#38; (pos &#60; end) &#38; &#126;UserInterrupt DO &#9;&#9;pos &#58;&#61; Texts.Pos(S) - 1; &#9;&#9;Oberon.Par.vwr &#58;&#61; Oberon.MarkedViewer; &#9;&#9;Oberon.Par.frame &#58;&#61; Oberon.MarkedFrame; &#9;&#9;Oberon.Par.text &#58;&#61; T; Oberon.Par.pos &#58;&#61; pos; &#9;&#9;Oberon.Call(S.s, Oberon.Par, FALSE, res); &#9;&#9;IF res # 0 THEN &#9;&#9;&#9;Texts.WriteString(W, "Call error&#58; "); Texts.WriteString(W, Modules.resMsg); &#9;&#9;&#9;Texts.WriteLn(W); Texts.Append(Oberon.Log, W.buf) &#9;&#9;END; &#9;&#9;NextCmd &#9;END END do; (** Configuration.DoText ( "*" &#124; "^" &#124; textfile &#123; textfile &#125; "&#126;" ) &#9;&#9;Execute the commands in textfile . Each command must be written on a separate line. *) &#9;PROCEDURE DoText*; &#9;VAR S&#58; Texts.Scanner; T&#58; Texts.Text; &#9;BEGIN &#9;&#9;OpenScanner(S); &#9;&#9;IF (S.class &#61; Texts.Char) &#38; (S.c &#61; "*") THEN &#9;&#9;&#9;T &#58;&#61; Oberon.MarkedText &#9;&#9;ELSIF S.class IN &#123;Texts.Name, Texts.String&#125; THEN &#9;&#9;&#9;NEW(T); Texts.Open(T, S.s) &#9;&#9;ELSE &#9;&#9;&#9;T &#58;&#61; NIL &#9;&#9;END; &#9;&#9;IF T # NIL THEN &#9;&#9;&#9;do(T, 0, T.len) &#9;&#9;END &#9;END DoText; (** Configuration.DoCommands ( "^" &#124; cmd &#123; cmd &#125; "&#126;" ) &#9;&#9;Execute the commands. Each command must be written on a separate line. *) PROCEDURE DoCommands*; &#9;VAR &#9;&#9;S&#58; Texts.Scanner; T&#58; Texts.Text; &#9;&#9;beg, end, time&#58; LONGINT; BEGIN &#9;Texts.OpenScanner(S, Oberon.Par.text, Oberon.Par.pos); &#9;Texts.Scan(S); &#9;IF (S.class &#61; Texts.Char) &#38; (S.c &#61; "^") THEN &#9;&#9;T &#58;&#61; NIL; time &#58;&#61; -1; Oberon.GetSelection(T, beg, end, time); &#9;ELSE &#9;&#9;T &#58;&#61; Oberon.Par.text; beg &#58;&#61; Oberon.Par.pos; end &#58;&#61; T.len &#9;END; &#9;IF T # NIL THEN &#9;&#9;do(T, beg, end) &#9;END END DoCommands; PROCEDURE ValidX(X&#58; INTEGER)&#58; BOOLEAN; BEGIN &#9;RETURN (Display.Left &#60;&#61; X) &#38; (X &#60; Display.Left + Display.Width) &#9;&#9;&#9;OR (Display.ColLeft &#60;&#61; X) &#38; (X &#60; Display.ColLeft + Display.Width) END ValidX; PROCEDURE ValidY(Y&#58; INTEGER)&#58; BOOLEAN; BEGIN &#9;RETURN (Display.Bottom &#60;&#61; Y) &#38; (Y &#60; Display.Bottom + Display.Height) END ValidY; (** Set the star marker under program control&#58; &#9;Configuration.Marker set save		(* set at saved position *) &#9;Configuration.Marker set this		(* set to current viewer *) &#9;Configuration.Marker set system		(* in system track *) &#9;Configuration.Marker set user		(* in user track *) &#9;Configuration.Marker set X Y		(* at absolute pixel position X, Y *) &#9;Configuration.Marker set X% Y%		(* at relative pixel position X, Y *) &#9;Configuration.Marker save system		(* save marker in system track *) &#9;Configuration.Marker save user		(* save marker in user track *) &#42;) PROCEDURE Marker*; &#9;VAR S&#58; Texts.Scanner;	V &#58; Viewers.Viewer;	cM&#58; Oberon.ControlMsg; BEGIN &#9;Texts.OpenScanner(S, Oberon.Par.text, Oberon.Par.pos); Texts.Scan(S); &#9;IF S.class # Texts.Name THEN RETURN END; &#9;IF S.s &#61; "set" THEN &#9;&#9;Texts.Scan(S); cM.id &#58;&#61; Oberon.mark + 999; &#9;&#9;IF (S.class &#61; Texts.Name) &#38; (S.s &#61; "saved") THEN &#9;&#9;&#9;V &#58;&#61; Viewers.This(sX + 1, sY - 1); &#9;&#9;&#9;IF (V # NIL) &#38; (V.X &#61; sX) &#38; (V.Y + V.H &#61; sY) THEN &#9;&#9;&#9;&#9;cM.id &#58;&#61; Oberon.mark; cM.X &#58;&#61; V.X + V.W DIV 2; cM.Y &#58;&#61; V.Y + V.H DIV 2 &#9;&#9;&#9;END &#9;&#9;ELSIF (S.class &#61; Texts.Name) &#38; (S.s &#61; "this") THEN &#9;&#9;&#9;IF Oberon.Par.vwr # NIL THEN &#9;&#9;&#9;&#9;cM.id &#58;&#61; Oberon.mark; cM.X &#58;&#61; Oberon.Par.vwr.X + Oberon.Par.vwr.W DIV 2; &#9;&#9;&#9;&#9;cM.Y &#58;&#61; Oberon.Par.vwr.Y + Oberon.Par.vwr.H DIV 2 &#9;&#9;&#9;END &#9;&#9;ELSIF (S.class &#61; Texts.Name) &#38; (S.s &#61; "system") THEN &#9;&#9;&#9;Oberon.AllocateSystemViewer(Oberon.SystemTrack(Oberon.Par.vwr.X), cM.X, cM.Y); &#9;&#9;&#9;cM.id &#58;&#61; Oberon.mark; &#9;&#9;ELSIF (S.class &#61; Texts.Name) &#38; (S.s &#61; "user") THEN &#9;&#9;&#9;Oberon.AllocateUserViewer(Oberon.UserTrack(Oberon.Par.vwr.X), cM.X, cM.Y); &#9;&#9;&#9;cM.id &#58;&#61; Oberon.mark; &#9;&#9;ELSIF (S.class &#61; Texts.Int) &#38; (S.i &#62;&#61; 0) THEN &#9;&#9;&#9;cM.X &#58;&#61; SHORT(S.i); Texts.Scan(S); &#9;&#9;&#9;IF (S.class &#61; Texts.Int) &#38; (S.i &#62;&#61; 0) THEN &#9;&#9;&#9;&#9;cM.Y &#58;&#61; SHORT(S.i); &#9;&#9;&#9;&#9;IF ValidX(cM.X) &#38; ValidY(cM.Y) THEN cM.id &#58;&#61; Oberon.mark END &#9;&#9;&#9;ELSIF (S.class &#61; Texts.Char) &#38; (S.c &#61; "%") THEN &#9;&#9;&#9;&#9;Texts.Scan(S); &#9;&#9;&#9;&#9;IF (S.class &#61; Texts.Int) &#38; (S.i &#62;&#61; 0) THEN &#9;&#9;&#9;&#9;&#9;cM.Y &#58;&#61; SHORT(S.i*Display.Height DIV 100); &#9;&#9;&#9;&#9;&#9;cM.X &#58;&#61; SHORT(LONG(Display.Width)*cM.X DIV 100); &#9;&#9;&#9;&#9;&#9;IF ValidX(cM.X) &#38; ValidY(cM.Y) THEN cM.id &#58;&#61; Oberon.mark END &#9;&#9;&#9;&#9;END &#9;&#9;&#9;END &#9;&#9;END; &#9;&#9;IF cM.id &#61; Oberon.mark THEN &#9;&#9;&#9;IF cM.Y &#62;&#61; Display.Width THEN cM.Y &#58;&#61; Display.Width-1 END; &#9;&#9;&#9;V &#58;&#61; Viewers.This(cM.X, cM.Y); IF V # NIL THEN V.handle(V, cM) END	(* set marker *) &#9;&#9;END &#9;ELSIF S.s &#61; "save" THEN &#9;&#9;Texts.Scan(S); &#9;&#9;IF S.class &#61; Texts.Name THEN &#9;&#9;&#9;IF S.s &#61; "system" THEN &#9;&#9;&#9;&#9;Oberon.AllocateSystemViewer(Oberon.SystemTrack(Oberon.Par.vwr.X), sX, sY) &#9;&#9;&#9;ELSIF S.s &#61; "user" THEN &#9;&#9;&#9;&#9;Oberon.AllocateUserViewer(Oberon.UserTrack(Oberon.Par.vwr.X), sX, sY) &#9;&#9;&#9;ELSE sX &#58;&#61; -1; sY &#58;&#61; -1 &#9;&#9;&#9;END &#9;&#9;END &#9;END END Marker; PROCEDURE Init; &#9;VAR &#9;&#9;s&#58; Texts.Scanner; &#9;&#9;T&#58; Texts.Text; &#9;&#9;x, y&#58; INTEGER; BEGIN &#9;Oberon.OpenScanner(s, "System.Configuration"); &#9;IF &#126;(s.class IN &#123;Texts.Name, Texts.String&#125;) THEN &#9;&#9;COPY(Default, s.s) &#9;END; &#9;NEW(T); Texts.Open(T, s.s); &#9;IF T.len &#62; 0 THEN &#9;&#9;Oberon.AllocateSystemViewer(Display.Left, x, y); &#9;&#9;NEW(Oberon.Par); &#9;&#9;Oberon.Par.vwr &#58;&#61; Viewers.This(x+1, y-1); NEW(Oberon.Par.frame); &#9;&#9;do(T, 0, T.len) &#9;END END Init; BEGIN Texts.OpenWriter(W); Init END Configuration.