MODULE ObxFact;
(**
	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
		Stores, Models, TextModels, TextControllers, Integers;

	PROCEDURE Read(r: TextModels.Reader; VAR x: Integers.Integer);
		VAR i, len, beg: INTEGER; ch: CHAR; buf: POINTER TO ARRAY OF CHAR;
	BEGIN
		r.ReadChar(ch);
		WHILE ~r.eot & (ch <= " ") DO r.ReadChar(ch) END;
		ASSERT(~r.eot & (((ch >= "0") & (ch <= "9")) OR (ch = "-")));
		beg := r.Pos() - 1; len := 0;
		REPEAT INC(len); r.ReadChar(ch) UNTIL r.eot OR (ch < "0") OR (ch > "9");
		NEW(buf, len + 1);
		i := 0; r.SetPos(beg);
		REPEAT r.ReadChar(buf[i]); INC(i) UNTIL i = len;
		buf[i] := 0X;
		Integers.ConvertFromString(buf^, x)
	END Read;

	PROCEDURE Write(w: TextModels.Writer; x: Integers.Integer);
		VAR i: INTEGER;
	BEGIN
		IF Integers.Sign(x) < 0 THEN w.WriteChar("-") END;
		i := Integers.Digits10Of(x);
		IF i # 0 THEN
			REPEAT DEC(i); w.WriteChar(Integers.ThisDigit10(x, i)) UNTIL i = 0
		ELSE w.WriteChar("0")
		END
	END Write;

	PROCEDURE Compute*;
		VAR beg, end, i, n: INTEGER; ch: CHAR;
			s: Stores.Operation;
			r: TextModels.Reader; w: TextModels.Writer; attr: TextModels.Attributes;
			c: TextControllers.Controller;
			x: Integers.Integer;
	BEGIN
		c := TextControllers.Focus();
		IF (c # NIL) & c.HasSelection() THEN
			c.GetSelection(beg, end);
			r := c.text.NewReader(NIL); r.SetPos(beg); r.ReadChar(ch);
			WHILE ~r.eot & (beg < end) & (ch <= " ") DO r.ReadChar(ch); INC(beg) END;
			IF ~r.eot & (beg < end) THEN
				r.ReadPrev; Read(r, x);
				end := r.Pos(); r.ReadPrev; attr :=r.attr;
				IF (Integers.Sign(x) > 0) & (Integers.Compare(x, Integers.Long(MAX(LONGINT))) <= 0) THEN
					n := SHORT(Integers.Short(x)); i := 2; x := Integers.Long(1);
					WHILE i <= n DO x := Integers.Product(x, Integers.Long(i)); INC(i) END;
					Models.BeginScript(c.text, "computation", s);
					c.text.Delete(beg, end);
					w := c.text.NewWriter(NIL); w.SetPos(beg); w.SetAttr(attr);
					Write(w, x);
					Models.EndScript(c.text, s)
				END
			END
		END
	END Compute;

END ObxFact.

Menu entry:

	"Compute Factorial"	""	"ObxFact.Compute"	"TextCmds.SelectionGuard"
