hodza/BlackBox.Shkola.2014 huggingface dataset:
Obx/Mod/PhoneUI.odc

MODULE ObxPhoneUI;
(**
	project	= "BlackBox"
	organization	= "www.oberon.ch"
	contributors	= "Oberon microsystems"
	version	= "System/Rsrc/About"
	copyright	= "System/Rsrc/About"
	license	= "Docu/BB-License"
	changes	= "
	- YYYYMMDD, nn, ...
	"
	issues	= "
	- ...
	"

**)

	IMPORT Dialog, ObxPhoneDB;

	VAR
		phone*: RECORD
			name*, number*: ObxPhoneDB.String;
			lookupByName*: BOOLEAN
		END;

	PROCEDURE Lookup*;
	BEGIN
		IF phone.lookupByName THEN
			ObxPhoneDB.LookupByName(phone.name, phone.number);
			IF phone.number = "" THEN phone.number := "not found" END
		ELSE
			ObxPhoneDB.LookupByNumber(phone.number, phone.name);
			IF phone.name = "" THEN phone.name := "not found" END
		END;
		Dialog.Update(phone)
	END Lookup;

	PROCEDURE LookupGuard* (VAR par: Dialog.Par);
	BEGIN	(* disable if input string is empty *)
		par.disabled := phone.lookupByName & (phone.name = "") OR
							~phone.lookupByName & (phone.number = "")
	END LookupGuard;

	PROCEDURE NameGuard* (VAR par: Dialog.Par);
	BEGIN	(* make read-only if lookup is by number *)
		par.readOnly := ~phone.lookupByName
	END NameGuard;

	PROCEDURE NumberGuard* (VAR par: Dialog.Par);
	BEGIN	(* make read-only if lookup is by name *)
		par.readOnly := phone.lookupByName
	END NumberGuard;

END ObxPhoneUI.
Obx/Mod/PhoneUI1.odc

MODULE ObxPhoneUI1;
(**
	project	= "BlackBox"
	organization	= "www.oberon.ch"
	contributors	= "Oberon microsystems"
	version	= "System/Rsrc/About"
	copyright	= "System/Rsrc/About"
	license	= "Docu/BB-License"
	changes	= "
	- YYYYMMDD, nn, ...
	"
	issues	= "
	- ...
	"

**)

	IMPORT Dialog, ObxPhoneDB;

	VAR
		phone*: RECORD
			name*, number*: ObxPhoneDB.String
		END;

	PROCEDURE NameNotifier* (op, from, to: INTEGER);
	BEGIN
		ObxPhoneDB.LookupByName(phone.name, phone.number);
		Dialog.Update(phone)
	END NameNotifier;

	PROCEDURE NumberNotifier* (op, from, to: INTEGER);
	BEGIN
		ObxPhoneDB.LookupByNumber(phone.number, phone.name);
		Dialog.Update(phone)
	END NumberNotifier;

END ObxPhoneUI1.
Obx/Mod/Pi.odc

MODULE ObxPi;
(**
	project	= "BlackBox"
	organization	= "www.oberon.ch"
	contributors	= "Oberon microsystems"
	version	= "System/Rsrc/About"
	copyright	= "System/Rsrc/About"
	license	= "Docu/BB-License"
	changes	= "
	- YYYYMMDD, nn, ...
	"
	issues	= "
	- ...
	"

**)

	IMPORT Int := Integers, StdLog;

	PROCEDURE Pi* (digits: INTEGER): Int.Integer;	(* entier(pi * 10^digits) *)
		VAR p1, p2, inc, sum: Int.Integer; guard, div: INTEGER;
	BEGIN
		(* pi = 16 * atan(1/5) - 4 * atan(1/239) *)
		(* atan(x) = x - x^3/3 + x^5/5 - x^7/7 + ... *)
		guard := 8;
		p1 := Int.Quotient(Int.Product(Int.Power(Int.Long(10), digits + guard), Int.Long(16)), Int.Long(5));
		p2 := Int.Quotient(Int.Product(Int.Power(Int.Long(10), digits + guard), Int.Long(-4)), Int.Long(239));
		sum := Int.Sum(p1, p2);
		div := 1;
		REPEAT
			p1 := Int.Quotient(p1, Int.Long(-5 * 5));
			p2 := Int.Quotient(p2, Int.Long(-239 * 239));
			INC(div, 2);
			inc := Int.Quotient(Int.Sum(p1, p2), Int.Long(div));
			sum := Int.Sum(sum, inc)
		UNTIL Int.Sign(inc) = 0;
		RETURN Int.Quotient(sum, Int.Power(Int.Long(10), guard))
	END Pi;

	PROCEDURE WritePi* (digits: INTEGER);
		VAR i: Int.Integer; s: ARRAY 10000 OF CHAR;
	BEGIN
		i := Pi(digits);
		Int.ConvertToString(i, s);
		StdLog.String(s); StdLog.Ln
	END WritePi;

END ObxPi.
Obx/Mod/Random.odc

MODULE ObxRandom;
(**
	project	= "BlackBox"
	organization	= "www.oberon.ch"
	contributors	= "Oberon microsystems"
	version	= "System/Rsrc/About"
	references	= "Martin Reiser, Niklaus Wirth, Programming In Oberon, ISBN 0201565439"
	changes	= "
	- YYYYMMDD, nn, ...
	"
	issues	= "
	- ...
	"

**)

	VAR z: INTEGER;	(* global variable *)

	PROCEDURE Uniform* (): REAL;
		CONST a = 16807; m = 2147483647; q = m DIV a; r = m MOD a;
		VAR gamma: INTEGER;
	BEGIN
		gamma := a * (z MOD q) - r * (z DIV q);
		IF gamma > 0 THEN
			z := gamma
		ELSE
			z := gamma + m
		END;
		RETURN z * (1.0 / m)	(* value of the function *)
	END Uniform;

	PROCEDURE InitSeed* (seed: INTEGER);
	BEGIN
		z := seed
	END InitSeed;

BEGIN
	z := 314159	(* initial value of seed *)
END ObxRandom.
Obx/Mod/Sample.odc

MODULE ObxSample;
(**
	project	= "BlackBox"
	organization	= "www.oberon.ch"
	contributors	= "Oberon microsystems"
	version	= "System/Rsrc/About"
	copyright	= "System/Rsrc/About"
	license	= "Docu/BB-License"
	changes	= "
	- YYYYMMDD, nn, ...
	"
	issues	= "
	- ...
	"

**)

	TYPE
		File* = POINTER TO RECORD
			len: INTEGER	(* hidden instance variable *)
		END;

		Rider* = POINTER TO RECORD
			(* there may be several riders on one file *)
			file-: File;	(* read-only instance variable *)
			eof*: BOOLEAN;	(* fully exported instance variable *)
			pos: INTEGER	(* hidden instance variable *)
				(* Invariant: (pos >= 0) & (pos < file.len) *)
		END;

	PROCEDURE (f: File) GetLength* (OUT length: INTEGER), NEW;
	BEGIN
		length := f.len
	END GetLength;

	PROCEDURE (rd: Rider) SetPos* (pos: INTEGER), NEW;
	BEGIN
		(* assert invariants, so that errors may not be propagated across components *)
		ASSERT(pos >= 0); ASSERT(pos < rd.file.len);
		rd.pos := pos
	END SetPos;

	(* ... *)

END ObxSample.
Obx/Mod/Stores.odc

MODULE ObxStores;
(**
	project	= "BlackBox"
	organization	= "www.oberon.ch"
	contributors	= "Oberon microsystems"
	version	= "System/Rsrc/About"
	copyright	= "System/Rsrc/About"
	license	= "Docu/BB-License"
	changes	= "
	- YYYYMMDD, nn, ...
	"
	issues	= "
	- ...
	"

**)

	(*
	This example illustrates the persistency service implemented by Stores. It is shown how a graph
	of linked nodes can be externalized and internalized, maintaining invariants like objects refered to
	through multiple pointers and cycles. Stores also offeres a mechanism to just copy such a graph.
			
	To run the example, click on the commanders below:
		 ObxStores.WriteRead		 ObxStores.Copy
	*)

	IMPORT Dialog, Files, Stores;

	TYPE
		Node = POINTER TO RECORD (Stores.Store)
			a, b: Node
		END;

	(* Methods of Node *)

	PROCEDURE (n: Node) Externalize (VAR w: Stores.Writer);
	BEGIN
		w.WriteStore(n.a); w.WriteStore(n.b)
	END Externalize;

	PROCEDURE (n: Node) Internalize (VAR r: Stores.Reader);
		VAR s: Stores.Store;
	BEGIN
		r.ReadStore(s);
		IF (s # NIL) & (s IS Node) THEN n.a := s(Node) ELSE n.a := NIL END;
		r.ReadStore(s);
		IF (s # NIL) & (s IS Node) THEN n.b := s(Node) ELSE n.b := NIL END
	END Internalize;

	PROCEDURE (n: Node) CopyFrom (source: Stores.Store);
	BEGIN
		WITH source: Node DO
			IF source.a # NIL THEN n.a := Stores.CopyOf(source.a)(Node) ELSE n.b := NIL END;
			IF source.b # NIL THEN n.b := Stores.CopyOf(source.b)(Node) ELSE n.b := NIL END
		END
	END CopyFrom;

	(* Build and check a graph of Nodes *)
																						
	PROCEDURE NewGraph (): Node;
		VAR n: Node;
	BEGIN
		NEW(n);
		NEW(n.a); Stores.Join(n, n.a);
		NEW(n.b); Stores.Join(n, n.b);
		n.a.a := n.b; n.a.b := NIL; n.b.a := n.a; n.b.b := n.b;
		RETURN n
	END NewGraph;

	PROCEDURE GraphOk (n: Node): BOOLEAN;
	BEGIN
		RETURN (n # n.a) & (n # n.b) & (n.a # n.b) & (n.a.a = n.b) & (n.a.b = NIL) & (n.b.a = n.a) & (n.b.b = n.b)
			& Stores.Joined(n, n.a) & Stores.Joined(n, n.b)
	END GraphOk;


	(* Demonstrate Ex- and Internalization *)

	PROCEDURE WriteRead*;
		VAR n, m: Node; f: Files.File; w: Stores.Writer; r: Stores.Reader; s: Stores.Store;
	BEGIN
		(* allocate and check new graph *)
		n := NewGraph(); ASSERT(GraphOk(n), 1);

		(* externalize graph to a temporary file *)
		f := Files.dir.Temp();
		w.ConnectTo(f); w.WriteStore(n);

		(* read graph back from file *)
		r.ConnectTo(f); r.ReadStore(s); m := s(Node);

		(* check graph to be internalized with nodes correctly linked and joined *)
		ASSERT(GraphOk(m), 2);
		Dialog.ShowMsg("WriteRead test ok.")
	END WriteRead;


	(* Demonstrate Copying *)

	PROCEDURE Copy*;
		VAR n, m: Node;
	BEGIN
		(* allocate and check new graph *)
		n := NewGraph(); ASSERT(GraphOk(n), 1);

		(* copy entire graph *)
		m := Stores.CopyOf(n)(Node);

		(* check graph to be internalized with nodes correctly linked and joined *)
		ASSERT(GraphOk(m), 2);
		Dialog.ShowMsg("Copy test ok.")
	END Copy;

END ObxStores.
Obx/Mod/Tabs.odc

MODULE ObxTabs;
(**
	project	= "BlackBox"
	organization	= "www.oberon.ch"
	contributors	= "Oberon microsystems"
	version	= "System/Rsrc/About"
	copyright	= "System/Rsrc/About"
	license	= "Docu/BB-License"
	changes	= "
	- YYYYMMDD, nn, ...
	"
	issues	= "
	- ...
	"

**)

	IMPORT Views, TextModels, TextViews, TextControllers;

	CONST tab = 09X; line = 0DX;

	VAR field: ARRAY 256 OF CHAR;

	PROCEDURE ReadField (r: TextModels.Reader);
		VAR i: INTEGER; ch: CHAR;
	BEGIN	(* read a field, which is a sequence of characters terminated by the end of text, or a tab or line character *)
		i := 0; r.ReadChar(ch);
		WHILE ~r.eot & (ch # tab) & (ch # line) DO
			field[i] := ch; INC(i); r.ReadChar(ch)
		END;
		field[i] := 0X
	END ReadField;

	PROCEDURE WriteField (w: TextModels.Writer);
		VAR i: INTEGER; ch: CHAR;
	BEGIN
		i := 0; ch := field[0];
		WHILE ch # 0X DO
			w.WriteChar(ch); INC(i); ch := field[i]
		END
	END WriteField;

	PROCEDURE Convert*;
		VAR c: TextControllers.Controller; t: TextModels.Model; r: TextModels.Reader;
			w: TextModels.Writer; beg, end: INTEGER;
	BEGIN
		c := TextControllers.Focus();
		IF (c # NIL) & c.HasSelection() THEN
			c.GetSelection(beg, end);
			r := c.text.NewReader(NIL); r.SetPos(beg);
			t := TextModels.CloneOf(c.text);
			w := t.NewWriter(NIL);
			ReadField(r);	(* title *)
			WHILE ~r.eot DO
				WriteField(w); w.WriteChar(" ");
				ReadField(r); WriteField(w); w.WriteChar(" ");	(* first name *)
				ReadField(r); WriteField(w); w.WriteChar(tab);	(* name *)
				ReadField(r); WriteField(w); w.WriteChar(tab);	(* company 1 *)
				ReadField(r); WriteField(w); w.WriteChar(tab);	(* company 2 *)
				ReadField(r); WriteField(w); w.WriteChar(tab);	(* address *)
				ReadField(r); WriteField(w); w.WriteChar(" ");	(* ZIP *)
				ReadField(r); WriteField(w); w.WriteChar(tab);	(* city *)
				ReadField(r); WriteField(w); w.WriteChar(line);	(* country *)
				ReadField(r)	(* title *)
			END;
			Views.OpenView(TextViews.dir.New(t))
		END
	END Convert;

END ObxTabs.
Obx/Mod/TabViews.odc

MODULE ObxTabViews;
(**
	project	= "BlackBox"
	organization	= "www.oberon.ch"
	contributors	= "Oberon microsystems"
	version	= "System/Rsrc/About"
	copyright	= "System/Rsrc/About"
	license	= "Docu/BB-License"
	changes	= "
	- YYYYMMDD, nn, ...
	"
	issues	= "
	- ...
	"

**)

	IMPORT StdTabViews, Views, Strings, Dialog, StdLog,
				ObxCalc, ObxCubes;
	
	VAR 
		st: StdTabViews.View;
		calc: Views.View;

	PROCEDURE New* (): StdTabViews.View;
		VAR v: Views.View;
	BEGIN
		st := StdTabViews.dir.New();
		calc := ObxCalc.New(); v := ObxCubes.New();
		st.SetItem(0, 'Cube', v);
		st.SetItem(1, 'Calc 1', calc);
		st.SetItem(2, 'Calc 2', calc);
		st.SetNotifier("ObxTabViews.Notify");
		RETURN st
	END New;

	PROCEDURE Deposit*;
	BEGIN
		Views.Deposit(New())
	END Deposit;
	
	PROCEDURE AddNewCalc*;
		VAR s: ARRAY 4 OF CHAR;
	BEGIN
		Strings.IntToString(st.NofTabs(), s);
		st.SetItem(st.NofTabs(), 'Calc ' + s, calc)
	END AddNewCalc;
	
	PROCEDURE DeleteTab*;
		VAR i: INTEGER; s: Dialog.String; v: Views.View;
	BEGIN
		IF st.NofTabs() > 0 THEN
			FOR i := st.Index() TO st.NofTabs() - 2 DO
				st.GetItem(i + 1, s, v); st.SetItem(i, s, v)
			END;
			st.SetNofTabs(st.NofTabs() - 1)
		END
	END DeleteTab;
	
	PROCEDURE Notify* (v: StdTabViews.View; from, to: INTEGER);
	BEGIN
		StdLog.String("Notify: "); StdLog.Int(from); StdLog.Int(to); StdLog.Ln
	END Notify;
	
END ObxTabViews.
Obx/Mod/Trap.odc

MODULE ObxTrap;
(**
	project	= "BlackBox"
	organization	= "www.oberon.ch"
	contributors	= "Oberon microsystems"
	version	= "System/Rsrc/About"
	copyright	= "System/Rsrc/About"
	license	= "Docu/BB-License"
	changes	= "
	- YYYYMMDD, nn, ...
	"
	issues	= "
	- ...
	"

**)

	IMPORT Dialog, Views, Controllers;

	VAR global: INTEGER;

	PROCEDURE Do*;
		VAR i: INTEGER; str: Dialog.String; v: Views.View;
	BEGIN
		str := "String";
		global := 13;
		v := Controllers.FocusView();
		i := 777;
		str[i] := "*"	(* index out of range, since the Dialog.String array only contains 256 elements *)
	END Do;

END ObxTrap.
Obx/Mod/UnitConv.odc

MODULE ObxUnitConv;
(**
	project	= "BlackBox"
	organization	= "www.oberon.ch"
	contributors	= "Oberon microsystems"
	version	= "System/Rsrc/About"
	copyright	= "System/Rsrc/About"
	license	= "Docu/BB-License"
	changes	= "
	- YYYYMMDD, nn, ...
	"
	issues	= "
	- ...
	"

**)

	IMPORT Ports, Dialog;

	VAR
		par*: RECORD metric*, inch*, point*: REAL; metricUnit*: Dialog.List END;
		metricUnits: ARRAY 4 OF INTEGER;

	PROCEDURE NotifyMetric* (op, from, to: INTEGER);
		VAR units: REAL;
	BEGIN
		units := par.metric * metricUnits[par.metricUnit.index] * Ports.mm;
		par.inch := units / Ports.inch; par.point := units / Ports.point;
		Dialog.Update(par)
	END NotifyMetric;

	PROCEDURE NotifyInch* (op, from, to: INTEGER);
		VAR units: REAL;
	BEGIN
		units := par.inch * Ports.inch;
		par.metric := units / metricUnits[par.metricUnit.index] / Ports.mm; par.point := units / Ports.point;
		Dialog.Update(par)
	END NotifyInch;

	PROCEDURE NotifyPoint* (op, from, to: INTEGER);
		VAR units: REAL;
	BEGIN
		units := par.point * Ports.point;
		par.metric := units / metricUnits[par.metricUnit.index] / Ports.mm; par.inch := units / Ports.inch;
		Dialog.Update(par)
	END NotifyPoint;

BEGIN
	par.metricUnit.SetLen(4);
	par.metricUnit.SetItem(0, "mm"); metricUnits[0] := 1;
	par.metricUnit.SetItem(1, "cm"); metricUnits[1] := 10;
	par.metricUnit.SetItem(2, "m"); metricUnits[2] := 1000;
	par.metricUnit.SetItem(3, "km"); metricUnits[3] := 1000000
END ObxUnitConv.
Obx/Mod/Views0.odc

MODULE ObxViews0;
(**
	project	= "BlackBox"
	organization	= "www.oberon.ch"
	contributors	= "Oberon microsystems"
	version	= "System/Rsrc/About"
	copyright	= "System/Rsrc/About"
	license	= "Docu/BB-License"
	changes	= "
	- YYYYMMDD, nn, ...
	"
	issues	= "
	- ...
	"

**)

	IMPORT Views, Ports;

	TYPE View = POINTER TO RECORD (Views.View) END;

	PROCEDURE (v: View)  Restore (f: Views.Frame; l, t, r, b: INTEGER);
	BEGIN
		f.DrawRect(l, t, r, b, Ports.fill, Ports.red)
	END Restore;

	PROCEDURE Deposit*;
		VAR v: View;
	BEGIN
		NEW(v); Views.Deposit(v)
	END Deposit;

END ObxViews0.
Obx/Mod/Views1.odc

MODULE ObxViews1;
(**
	project	= "BlackBox"
	organization	= "www.oberon.ch"
	contributors	= "Oberon microsystems"
	version	= "System/Rsrc/About"
	copyright	= "System/Rsrc/About"
	license	= "Docu/BB-License"
	changes	= "
	- YYYYMMDD, nn, ...
	"
	issues	= "
	- ...
	"

**)

	IMPORT Views, Ports, Properties;

	TYPE View = POINTER TO RECORD (Views.View) END;

	PROCEDURE (v: View)  Restore (f: Views.Frame; l, t, r, b: INTEGER);
	BEGIN
		f.DrawRect(l, t, r, b, Ports.fill, Ports.red)
	END Restore;

	PROCEDURE (v: View) HandlePropMsg (VAR msg: Properties.Message);
	BEGIN
		WITH msg: Properties.SizePref DO
			IF (msg.w = Views.undefined) OR (msg.h = Views.undefined) THEN
				 msg.w := 20 * Ports.mm; msg.h := 10 * Ports.mm
			END
		ELSE	(* ignore other messages *)
		END
	END HandlePropMsg;

	PROCEDURE Deposit*;
		VAR v: View;
	BEGIN
		NEW(v); Views.Deposit(v)
	END Deposit;

END ObxViews1.
Obx/Mod/Views10.odc

MODULE ObxViews10;
(**
	project	= "BlackBox"
	organization	= "www.oberon.ch"
	contributors	= "Oberon microsystems"
	version	= "System/Rsrc/About"
	copyright	= "System/Rsrc/About"
	license	= "Docu/BB-License"
	changes	= "
	- YYYYMMDD, nn, ...
	"
	issues	= "
	- ...
	"

**)

	IMPORT Fonts, Ports, Views, Controllers, Properties;

	CONST d = 20 * Ports.point;

	TYPE
		View = POINTER TO RECORD (Views.View)
			i: INTEGER;				(* position of next free slot in string *)
			s: ARRAY 256 OF CHAR	(* string *)
		END;

	PROCEDURE (v: View) Restore (f: Views.Frame; l, t, r, b: INTEGER);
	BEGIN
		f.DrawString(d, d, Ports.black, v.s, Fonts.dir.Default())
	END Restore;

	PROCEDURE (v: View) HandleCtrlMsg (f: Views.Frame;
										VAR msg: Controllers.Message; 
										VAR focus: Views.View);
	BEGIN
		WITH msg: Controllers.EditMsg DO
			IF msg.op = Controllers.pasteChar THEN	(* accept typing *)
				v.s[v.i] := msg.char; INC(v.i); v.s[v.i] := 0X;	(* append character to string *)
				Views.Update(v, Views.keepFrames)	(* restore v in any frame that displays it *)
			END
		ELSE						(* ignore other messages *)
		END
	END HandleCtrlMsg;
	
	PROCEDURE (v:View) HandlePropMsg (VAR msg: Properties.Message);
	BEGIN
		WITH msg: Properties.SizePref DO
			IF (msg.w = Views.undefined) OR (msg.h = Views.undefined) THEN 
				msg.w := 10 * d; msg.h := 2 * d
			END
		| msg: Properties.FocusPref DO
			msg.setFocus := TRUE
		ELSE
		END
	END HandlePropMsg;

	PROCEDURE Deposit*;
		VAR v: View;
	BEGIN
		NEW(v); v.s := ""; v.i := 0;
		Views.Deposit(v)
	END Deposit;

END ObxViews10.
Obx/Mod/Views11.odc

MODULE ObxViews11;
(**
	project	= "BlackBox"
	organization	= "www.oberon.ch"
	contributors	= "Oberon microsystems"
	version	= "System/Rsrc/About"
	copyright	= "System/Rsrc/About"
	license	= "Docu/BB-License"
	purpose	= "Same as ObxViews10, but the view's string can be stored and copied"
	changes	= "
	- YYYYMMDD, nn, ...
	"
	issues	= "
	- ...
	"

**)

	IMPORT Fonts, Ports, Stores, Views, Controllers, Properties;

	CONST d = 20 * Ports.point;

	TYPE
		View = POINTER TO RECORD (Views.View)
			i: INTEGER;					(* position of next free slot in string *)
			s: ARRAY 256 OF CHAR		(* string *)
		END;

	PROCEDURE (v: View) Internalize (VAR rd: Stores.Reader);
		VAR version: INTEGER;
	BEGIN
		rd.ReadVersion(0, 0, version);
		IF ~rd.cancelled THEN
			rd.ReadInt(v.i); rd.ReadString(v.s)
		END
	END Internalize;

	PROCEDURE (v: View) Externalize (VAR wr: Stores.Writer);
	BEGIN
		wr.WriteVersion(0);
		wr.WriteInt(v.i); wr.WriteString(v.s)
	END Externalize;

	PROCEDURE (v: View) CopyFromSimpleView (source: Views.View);
	BEGIN
		WITH source: View DO
			v.i := source.i; v.s := source.s
		END
	END CopyFromSimpleView;

	PROCEDURE (v: View) Restore (f: Views.Frame; l, t, r, b: INTEGER);
	BEGIN
		f.DrawString(d, d, Ports.black, v.s, Fonts.dir.Default())
	END Restore;

	PROCEDURE (v: View) HandleCtrlMsg (f: Views.Frame;
											VAR msg: Controllers.Message;
											VAR focus: Views.View);
	BEGIN
		WITH msg: Controllers.EditMsg DO
			IF msg.op = Controllers.pasteChar THEN	(* accept typing *)
				v.s[v.i] := msg.char; INC(v.i); v.s[v.i] := 0X;	(* append character to string *)
				Views.SetDirty(v);	(* mark view's document as dirty *)
				Views.Update(v, Views.keepFrames)	(* restore v in any frame that displays it *)
			END
		ELSE							(* ignore other messages *)
		END
	END HandleCtrlMsg;

	PROCEDURE (v:View) HandlePropMsg (VAR msg: Properties.Message);
	BEGIN
		WITH msg: Properties.SizePref DO
			IF (msg.w = Views.undefined) OR (msg.h = Views.undefined) THEN
				msg.w := 10 * d; msg.h := 2 * d
			END
		| msg: Properties.FocusPref DO
			msg.setFocus := TRUE
		ELSE
		END
	END HandlePropMsg;

	PROCEDURE Deposit*;
		VAR v: View;
	BEGIN
		NEW(v); v.s := ""; v.i := 0;
		Views.Deposit(v)
	END Deposit;

END ObxViews11.
Obx/Mod/Views12.odc

MODULE ObxViews12;
(**
	project	= "BlackBox"
	organization	= "www.oberon.ch"
	contributors	= "Oberon microsystems"
	version	= "System/Rsrc/About"
	copyright	= "System/Rsrc/About"
	license	= "Docu/BB-License"
	purpose	= "Same as ObxViews11, but uses a separate model for the string"
	changes	= "
	- YYYYMMDD, nn, ...
	"
	issues	= "
	- ...
	"

**)

	IMPORT Fonts, Ports, Stores, Models, Views, Controllers, Properties;

	CONST d = 20 * Ports.point;

	TYPE
		Model = POINTER TO RECORD (Models.Model)
			i: INTEGER;			(* position of next free slot in string *)
			s: ARRAY 256 OF CHAR	(* string *)
		END;

		View = POINTER TO RECORD (Views.View)
			model: Model
		END;


	(* Model *)

	PROCEDURE (m: Model) Internalize (VAR rd: Stores.Reader);
		VAR version: INTEGER;
	BEGIN
		rd.ReadVersion(0, 0, version);
		IF ~rd.cancelled THEN
			rd.ReadInt(m.i); rd.ReadString(m.s)
		END
	END Internalize;

	PROCEDURE (m: Model) Externalize (VAR wr: Stores.Writer);
	BEGIN
		wr.WriteVersion(0);
		wr.WriteInt(m.i); wr.WriteString(m.s)
	END Externalize;

	PROCEDURE (m: Model) CopyFrom (source: Stores.Store);
	BEGIN
		WITH source: Model DO
			m.i := source.i; m.s := source.s
		END
	END CopyFrom;


	(* View *)

	PROCEDURE (v: View) Internalize (VAR rd: Stores.Reader);
		VAR version: INTEGER; st: Stores.Store;
	BEGIN
		rd.ReadVersion(0, 0, version);
		IF ~rd.cancelled THEN
			rd.ReadStore(st);
			v.model := st(Model)
		END
	END Internalize;

	PROCEDURE (v: View) Externalize (VAR wr: Stores.Writer);
	BEGIN
		wr.WriteVersion(0);
		wr.WriteStore(v.model)
	END Externalize;

	PROCEDURE (v: View) CopyFromModelView (source: Views.View; model: Models.Model);
	BEGIN
		v.model := model(Model)
	END CopyFromModelView;

	PROCEDURE (v: View) Restore (f: Views.Frame; l, t, r, b: INTEGER);
	BEGIN
		f.DrawString(d, d, Ports.black, v.model.s, Fonts.dir.Default())
	END Restore;

	PROCEDURE (v: View) ThisModel (): Models.Model;
	BEGIN
		RETURN v.model
	END ThisModel;

	PROCEDURE (v: View) HandleModelMsg (VAR msg: Models.Message);
	BEGIN
		Views.Update(v, Views.keepFrames)	(* restore v in any frame that displays it *)
	END HandleModelMsg;

	PROCEDURE (v: View) HandleCtrlMsg (f: Views.Frame;
										VAR msg: Controllers.Message;
										VAR focus: Views.View);
		VAR m: Model; umsg: Models.UpdateMsg;
	BEGIN
		WITH msg: Controllers.EditMsg DO
			IF msg.op = Controllers.pasteChar THEN
				m := v.model;
				m.s[m.i] := msg.char; INC(m.i);
				m.s[m.i] := 0X;	(* append character to string *)
				Views.SetDirty(v);	(* mark view's document as dirty *)
				Models.Broadcast(m, umsg)	(* update all views on this model *)
			END
		ELSE						(* ignore other messages *)
		END
	END HandleCtrlMsg;

	PROCEDURE (v:View) HandlePropMsg (VAR msg: Properties.Message);
	BEGIN
		WITH msg: Properties.SizePref DO
			IF (msg.w = Views.undefined) OR (msg.h = Views.undefined) THEN
				msg.w := 10 * d; msg.h := 2 * d
			END
		| msg: Properties.FocusPref DO
			msg.setFocus := TRUE
		ELSE
		END
	END HandlePropMsg;

	PROCEDURE Deposit*;
		VAR v: View; m: Model;
	BEGIN
		NEW(m); m.i := 0; m.s := "";
		NEW(v); v.model := m; Stores.Join(v, m);
		Views.Deposit(v)
	END Deposit;

END ObxViews12.
Obx/Mod/Views2.odc

MODULE ObxViews2;
(**
	project	= "BlackBox"
	organization	= "www.oberon.ch"
	contributors	= "Oberon microsystems"
	version	= "System/Rsrc/About"
	copyright	= "System/Rsrc/About"
	license	= "Docu/BB-License"
	changes	= "
	- YYYYMMDD, nn, ...
	"
	issues	= "
	- ...
	"

**)

	IMPORT Views, Ports, Properties;

	TYPE View = POINTER TO RECORD (Views.View) END;

	PROCEDURE (v: View)  Restore (f: Views.Frame; l, t, r, b: INTEGER);
	BEGIN
		f.DrawRect(l, t, r, b, Ports.fill, Ports.red)
	END Restore;

	PROCEDURE (v: View) HandlePropMsg (VAR msg: Properties.Message);
		CONST min = 5 * Ports.mm; max = 50 * Ports.mm;
	BEGIN
		WITH msg: Properties.SizePref DO
			IF (msg.w = Views.undefined) OR (msg.h = Views.undefined) THEN
				 msg.w := 20 * Ports.mm; msg.h := 10 * Ports.mm
			ELSE
				Properties.ProportionalConstraint(2, 1, msg.fixedW, msg.fixedH,
										msg.w, msg.h);
				IF msg.h < min THEN
					msg.h := min; msg.w := 2 * min
				ELSIF msg.h > max THEN
					msg.h := max; msg.w := 2 * max
				END
			END
		ELSE	(* ignore other messages *)
		END
	END HandlePropMsg;

	PROCEDURE Deposit*;
		VAR v: View;
	BEGIN
		NEW(v); Views.Deposit(v)
	END Deposit;

END ObxViews2.