MODULE System; (*JG 3.10.90*)

	IMPORT Viewers, MenuViewers, Oberon, Texts, TextFrames;

	CONST
		StandardMenu = "System.Close System.Copy System.Grow Edit.Search Edit.Store";
		LogMenu = "System.Close System.Grow Edit.Locate Edit.Store";

	VAR W: Texts.Writer;

	PROCEDURE Max (i, j: LONGINT): LONGINT;
	BEGIN IF i >= j THEN RETURN i ELSE RETURN j END
	END Max;

	(* ------------- Toolbox for standard display ---------------*)

	PROCEDURE Open*;
		VAR par: Oberon.ParList;
			V: Viewers.Viewer;
			T: Texts.Text; S: Texts.Scanner;
			X, Y: INTEGER;
			beg, end, time: LONGINT;
	BEGIN
		par := Oberon.Par;
		Texts.OpenScanner(S, par.text, par.pos); Texts.Scan(S);
		IF (S.class = Texts.Char) & (S.c = "^") OR (S.line # 0) THEN
			Oberon.GetSelection(T, beg, end, time);
			IF time >= 0 THEN Texts.OpenScanner(S, T, beg); Texts.Scan(S) END
		END;
		IF S.class = Texts.Name THEN
			Oberon.AllocateSystemViewer(par.vwr.X, X, Y);
			V := MenuViewers.New(
				TextFrames.NewMenu(S.s, StandardMenu),
				TextFrames.NewText(TextFrames.Text(S.s), 0),
				TextFrames.menuH,
				X, Y)
		END
	END Open;

	PROCEDURE OpenLog*;
		VAR V: Viewers.Viewer; X, Y: INTEGER;
	BEGIN
		Oberon.AllocateSystemViewer(Oberon.Par.vwr.X, X, Y);
		V := MenuViewers.New(
			TextFrames.NewMenu("System.Log", LogMenu),
			TextFrames.NewText(Oberon.Log, Max(0, Oberon.Log.len - 200)),
			TextFrames.menuH,
			X, Y)
	END OpenLog;

	PROCEDURE Close*;
		VAR par: Oberon.ParList; V: Viewers.Viewer;
	BEGIN par := Oberon.Par;
		IF par.frame = par.vwr.dsc THEN V := par.vwr
		ELSE V := Oberon.MarkedViewer()
		END;
		Viewers.Close(V)
	END Close;

	PROCEDURE CloseTrack*;
		VAR V: Viewers.Viewer;
	BEGIN V := Oberon.MarkedViewer(); Viewers.CloseTrack(V.X)
	END CloseTrack;

	PROCEDURE Recall*;
		VAR V: Viewers.Viewer; M: Viewers.ViewerMsg;
	BEGIN
		Viewers.Recall(V);
		IF V.state = 0 THEN
			Viewers.Open(V, V.X, V.Y + V.H); M.id := Viewers.restore; V.handle(V, M)
		END
	END Recall;

	PROCEDURE Copy*;
		VAR V, V1: Viewers.Viewer; M: Oberon.CopyMsg; N: Viewers.ViewerMsg;
	BEGIN
		V := Oberon.Par.vwr; V.handle(V, M); V1 := M.F(Viewers.Viewer);
		Viewers.Open(V1, V.X, V.Y + V.H DIV 2);
		N.id := Viewers.restore; V1.handle(V1, N)
	END Copy;

	PROCEDURE Grow*;
		VAR V, V1: Viewers.Viewer; M: Oberon.CopyMsg; N: Viewers.ViewerMsg;
			DW, DH: INTEGER;
	BEGIN V := Oberon.Par.vwr;
		DW := Oberon.DisplayWidth(V.X); DH := Oberon.DisplayHeight(V.X);
		IF V.H < DH - Viewers.minH THEN Oberon.OpenTrack(V.X, V.W)
		ELSIF V.W < DW THEN Oberon.OpenTrack(Oberon.UserTrack(V.X), DW)
		END;
		IF (V.H < DH - Viewers.minH) OR (V.W < DW) THEN
			V.handle(V, M); V1 := M.F(Viewers.Viewer);
			Viewers.Open(V1, V.X, DH);
			N.id := Viewers.restore; V1.handle(V1, N)
		END
	END Grow;

	PROCEDURE OpenViewers;
		VAR V: Viewers.Viewer; t, d: LONGINT; X, Y: INTEGER;
	BEGIN
		Oberon.GetClock(t, d); Texts.WriteString(W, "System.Time");
		Texts.WriteDate(W, t, d); Texts.WriteLn(W); Texts.Append(Oberon.Log, W.buf);
		Oberon.AllocateSystemViewer(0, X, Y);
		V := MenuViewers.New(
			TextFrames.NewMenu("System.Log", LogMenu),
			TextFrames.NewText(Oberon.Log, 0),
			TextFrames.menuH,
			X, Y);
		Oberon.AllocateSystemViewer(0, X, Y);
		V := MenuViewers.New(
			TextFrames.NewMenu("System.Tool", StandardMenu),
			TextFrames.NewText(TextFrames.Text("System.Tool"), 0),
			TextFrames.menuH,
			X, Y)
	END OpenViewers;

BEGIN
	Texts.OpenWriter(W);
	Oberon.Log := TextFrames.Text("");
	OpenViewers
END System.