home *** CD-ROM | disk | FTP | other *** search
/ Amiga MA Magazine 1998 #6 / amigamamagazinepolishissue1998.iso / coders / jËzyki_programowania / oberon / nonfpu / colors.mod (.txt) < prev    next >
Oberon Text  |  1977-12-31  |  17KB  |  399 lines

  1. Syntax24b.Scn.Fnt
  2. ParcElems
  3. Alloc
  4. Syntax10.Scn.Fnt
  5. Syntax10i.Scn.Fnt
  6. (* Amiga NonFPU *) 
  7. MODULE Colors; (** ww 23 Jan 91 / RC 28.10.93**)
  8.   IMPORT Amiga, Display, Texts, TextFrames, Viewers, MenuViewers, Oberon, Input, Files, AmigaMath;
  9.   CONST Menu = "System.Close  System.Copy  System.Grow";
  10.     (*Cols = 16;  (* Number of Colors to be represented *)*)
  11.     MaxInt = 255;  (* maximum value for intensity *)
  12.     Left = 2; Middle = 1; Right = 0;  (* mouse buttons *)
  13.     Comp = 3; H = 0; L = 1; S = 2;  R = 0; G = 1; B = 2;  (* Just for clarifying some things later ... *)
  14. (* Colors 1 .. 3 are supposed to represent red green and blue. They are not editable with this tool. *)
  15.   TYPE
  16.     Frame = POINTER TO FrameDesc;
  17.     FrameDesc = RECORD(Display.FrameDesc)
  18.       beg: ARRAY 256 OF INTEGER;
  19.       n: INTEGER
  20.     END;
  21.     Components = ARRAY Comp OF REAL;
  22.     Color = RECORD
  23.       rgb, hls: Components;
  24.       nr: INTEGER
  25.     END;
  26.     EditFrame = POINTER TO EditFrameDesc;
  27.     EditFrameDesc = RECORD(Display.FrameDesc)
  28.       beg: ARRAY Comp + 1 OF INTEGER;
  29.       col: Color;
  30.       rgb: BOOLEAN
  31.     END;
  32.     Msg = RECORD(Display.FrameMsg) END;
  33.   VAR w: Texts.Writer; task: Oberon.Task; grey: ARRAY 3 OF Display.Pattern; Cols:INTEGER;
  34.   PROCEDURE UpdateRGB(VAR col: Color);
  35.     VAR c: REAL; i: INTEGER; Dum, Dum2: REAL;
  36.   BEGIN i := 0;
  37.     REPEAT
  38.       AmigaMath.IntToReal(i+2, Dum);
  39.       AmigaMath.Div(Dum, 3, Dum);
  40.       AmigaMath.Add(Dum, col.hls[H], c);
  41.       (* c := col.hls[H] + (i + 2) / 3;*)
  42.       WHILE AmigaMath.Cmp(c, 1)>0 DO AmigaMath.Sub(c, 1, c) END;
  43.       (* WHILE c > 1 DO c := c - 1 END; *)
  44.       IF AmigaMath.Cmp(c, 1/3)<0 THEN
  45.         AmigaMath.Sub(1, col.hls[S], Dum);
  46.         AmigaMath.Mul(Dum, col.hls[L], col.rgb[i]);
  47.       (* IF c < 1/3 THEN col.rgb[i] := (1 - col.hls[S]) * col.hls[L] *)
  48.       ELSIF AmigaMath.Cmp(c, 1/2)<=0 THEN
  49.         AmigaMath.Sub(1, col.hls[S], Dum);
  50.         AmigaMath.Sub(c, 1/3, Dum2);
  51.         AmigaMath.Mul(Dum2, 6, Dum2);
  52.         AmigaMath.Mul(Dum2, col.hls[S], Dum2);
  53.         AmigaMath.Add(Dum, Dum2, Dum);
  54.         AmigaMath.Mul(Dum, col.hls[L], col.rgb[i]);
  55.       (* ELSIF c <= 1/2 THEN col.rgb[i] := (1 - col.hls[S] + (c - 1 / 3) * 6 * col.hls[S]) * col.hls[L] *)
  56.       ELSIF AmigaMath.Cmp(c, 5/6)<=0 THEN col.rgb[i] := col.hls[L]
  57.       (* ELSIF c <= 5/6 THEN col.rgb[i] := col.hls[L] *)
  58.       ELSE 
  59.         AmigaMath.Sub(1, col.hls[S], Dum);
  60.         AmigaMath.Sub(1, c, Dum2);
  61.         AmigaMath.Mul(Dum2, 6, Dum2);
  62.         AmigaMath.Mul(Dum2, col.hls[S], Dum2);
  63.         AmigaMath.Add(Dum, Dum2, Dum);
  64.         AmigaMath.Mul(Dum, col.hls[L], col.rgb[i]);
  65.       (* ELSE col.rgb[i] := (1 - col.hls[S] + (1 - c) * 6 * col.hls[S]) * col.hls[L] *)
  66.       END;
  67.       INC(i)
  68.     UNTIL i = Comp
  69.   END UpdateRGB;
  70.   PROCEDURE UpdateHLS(VAR col: Color);
  71.     VAR max, min: REAL; Dum1, Dum2: REAL;
  72.     PROCEDURE Max(x, y: REAL; VAR z: REAL);
  73.     BEGIN
  74.       IF AmigaMath.Cmp(x, y)>0 THEN z:=x ELSE z:=y END
  75.     END Max;
  76.     (* PROCEDURE Max(x, y: REAL): REAL;
  77.     BEGIN
  78.       IF x > y THEN RETURN x ELSE RETURN y END
  79.     END Max;*)
  80.   BEGIN
  81.     Max(col.rgb[G], col.rgb[B], Dum1);
  82.     Max(col.rgb[R], Dum1, max);
  83.     (* max := Max(col.rgb[R], Max(col.rgb[G], col.rgb[B])); *)
  84.     AmigaMath.Neg(col.rgb[G], Dum1);
  85.     AmigaMath.Neg(col.rgb[B], Dum2);
  86.     Max(Dum1, Dum2, Dum1);
  87.     AmigaMath.Neg(col.rgb[R], Dum2);
  88.     Max(Dum1, Dum2, Dum1);
  89.     AmigaMath.Neg(Dum1, min);
  90.     (* min := -Max(-col.rgb[R], Max(-col.rgb[G], -col.rgb[B])); *)
  91.     col.hls[H] := 0; col.hls[L] := max; col.hls[S] := 0;
  92.     IF AmigaMath.Tst(max)>0 THEN
  93.     (* IF max > 0 THEN *)
  94.       AmigaMath.Sub(max, min, Dum1);
  95.       AmigaMath.Div(Dum1, max, col.hls[S]);
  96.       (* col.hls[S] := (max - min) / max; *)
  97.       IF AmigaMath.Tst(col.hls[S])>0 THEN
  98.       (* IF col.hls[S] > 0 THEN *)
  99.         AmigaMath.Mul(2, min, Dum1);
  100.         AmigaMath.Sub(max, Dum1, Dum1);
  101.         AmigaMath.Add(Dum1, col.rgb[B], Dum1);
  102.         AmigaMath.Sub(Dum1, col.rgb[R], Dum1);
  103.         AmigaMath.Add(Dum1, col.rgb[G], Dum1);
  104.         
  105.         AmigaMath.Sub(max, min, Dum2);
  106.         AmigaMath.Mul(6, Dum2, Dum2);
  107.         AmigaMath.Div(Dum1, Dum2, col.hls[H]);
  108.         (* col.hls[H] := (max - 2 * min + col.rgb[B] - col.rgb[R] + col.rgb[G]) / (6 * (max -min)); *)
  109.         IF (AmigaMath.Cmp(col.rgb[G], max)=0) OR (AmigaMath.Cmp(col.rgb[B], min)=0) THEN
  110.         (* IF (col.rgb[G] = max) OR (col.rgb[B] = min) THEN *)
  111.           AmigaMath.Sub(1, col.hls[H], col.hls[H]);
  112.           (* col.hls[H] := 1 - col.hls[H] *)
  113.         END
  114.       END
  115.     END
  116.   END UpdateHLS;
  117.   PROCEDURE Int(v: REAL): INTEGER;
  118.       VAR Dum: REAL;
  119.   BEGIN
  120.       AmigaMath.Mul(MaxInt, v, Dum);
  121.       RETURN SHORT(AmigaMath.Entier(Dum));
  122.       (* RETURN SHORT(ENTIER(MaxInt * v)) *)
  123.   END Int;
  124.   PROCEDURE UpdateDisp(VAR col: Color);
  125.   BEGIN Display.SetColor(col.nr, Int(col.rgb[0]), Int(col.rgb[1]), Int(col.rgb[2]))
  126.   END UpdateDisp;
  127.   PROCEDURE Change(VAR col: Color): BOOLEAN;
  128.     VAR d: ARRAY Comp OF INTEGER;  v: INTEGER (* REAL *); i: INTEGER; change: BOOLEAN; Dum: REAL;
  129.   BEGIN Display.GetColor(col.nr, d[0], d[1], d[2]); i := 0; change := FALSE;
  130.     WHILE i < Comp DO
  131.       v := Int(col.rgb[i]);
  132.       IF v # d[i] THEN
  133.        change := TRUE;
  134.        AmigaMath.IntToReal(d[i], Dum);
  135.        AmigaMath.Div(Dum, MaxInt, col.rgb[i]);
  136.        (* col.rgb[i] := d[i] / MaxInt *)
  137.       END;
  138.       INC(i)
  139.     END;
  140.     IF change THEN UpdateHLS(col) END;
  141.     RETURN change
  142.   END Change;
  143.   PROCEDURE ShowRGB(f: EditFrame);
  144.     VAR x, w, r, i, h: INTEGER; Dum: REAL;
  145.   BEGIN w := f.W DIV (Comp + 1) + 1; r := f.W - w * (Comp + 1); i := 0; x := 0; f.beg[i] := x; Oberon.RemoveMarks(f.X, f.Y, f.W, f.H);
  146.     WHILE i < Comp DO
  147.       AmigaMath.IntToReal(f.H, Dum);
  148.       AmigaMath.Mul(Dum, f.col.rgb[i], Dum);
  149.       h:=SHORT(AmigaMath.Entier(Dum));
  150.       (* h := SHORT(ENTIER(f.H * f.col.rgb[i]));*)
  151.       DEC(r);
  152.       IF r = 0 THEN DEC(w) END;
  153.       Display.ReplConst(i + 1, f.X + x, f.Y, w, h, Display.replace);
  154.       Display.ReplConst(Display.black, f.X + x, f.Y + h, w, f.H - h, Display.replace);
  155.       INC(x, w); INC(i); f.beg[i] := x
  156.     END;
  157.     Display.ReplConst(f.col.nr, f.X + x, f.Y, f.W - x, f.H, Display.replace)
  158.   END ShowRGB;
  159.   PROCEDURE ShowHLS(f: EditFrame);
  160.     VAR x, w, r, i, h: INTEGER; Dum: REAL;
  161.   BEGIN w := f.W DIV (Comp + 1); r := f.W - w * (Comp + 1); i := 0; x := 0; INC(w); f.beg[i] := x; Oberon.RemoveMarks(f.X, f.Y, f.W, f.H);
  162.     WHILE i < Comp DO
  163.       AmigaMath.IntToReal(f.H, Dum);
  164.       AmigaMath.Mul(Dum, f.col.hls[i], Dum);
  165.       h:=SHORT(AmigaMath.Entier(Dum));
  166.       (* h := SHORT(ENTIER(f.H * f.col.hls[i]));*)
  167.       IF r = 0 THEN DEC(w) END;
  168.       Display.ReplPattern(Display.white, grey[(i MOD 2) * 2], f.X + x, f.Y, w, h, Display.replace);
  169.       Display.ReplConst(Display.black, f.X + x, f.Y + h, w, f.H - h, Display.replace);
  170.       INC(x, w); INC(i); f.beg[i] := x; DEC(r)
  171.     END;
  172.     Display.ReplConst(f.col.nr, f.X + x, f.Y, f.W - x, f.H, Display.replace)
  173.   END ShowHLS;
  174.   PROCEDURE EditRGB(f: EditFrame; x, y: INTEGER; keys: SET);
  175.     VAR backUp: Color; m: Msg;  keySum: SET; last: REAL; i: INTEGER; Dumy, Dumh: REAL;
  176.   BEGIN keySum := keys; x := x - f.X; i := 1; backUp := f.col;
  177.     WHILE (i <= Comp) & (f.beg[i] < x) DO INC(i) END;
  178.     IF i <= Comp THEN DEC(i); last := -1;
  179.       REPEAT Input.Mouse(keys, x, y); keySum := keySum + keys;
  180.         Oberon.DrawCursor(Oberon.Mouse, Oberon.Mouse.marker, x, y); y := y - f.Y;
  181.         IF y < 0 THEN y := 0 ELSIF y > f.H THEN y := f.H END;
  182.         AmigaMath.IntToReal(y, Dumy);
  183.         AmigaMath.IntToReal(f.H, Dumh);
  184.         AmigaMath.Div(Dumy, Dumh, f.col.rgb[i]);
  185.         (* f.col.rgb[i] := y / f.H; *)
  186.         IF AmigaMath.Cmp(f.col.rgb[i], last)#0 THEN
  187.         (* IF f.col.rgb[i] # last THEN *)
  188.           UpdateHLS(f.col); UpdateDisp(f.col); last := f.col.rgb[i];
  189.           Oberon.RemoveMarks(f.X, f.Y, f.W, f.H);
  190.           Display.ReplConst(i + 1, f.X + f.beg[i], f.Y, f.beg[i + 1] - f.beg[i] , y, Display.replace);
  191.           Display.ReplConst(Display.black, f.X + f.beg[i], f.Y + y, f.beg[i + 1] - f.beg[i] , f.H - y, Display.replace);
  192.           Viewers.Broadcast(m)
  193.         END
  194.       UNTIL keys = {};
  195.       IF (keySum # {Left}) OR (f.col.nr > 0) & (f.col.nr < 4) THEN f.col := backUp; UpdateDisp(backUp); ShowRGB(f) END
  196.     END
  197.   END EditRGB;
  198.   PROCEDURE EditHLS(f: EditFrame; x, y: INTEGER; keys: SET);
  199.     VAR backUp: Color; m: Msg;  keySum: SET; last: REAL; i: INTEGER;Dumy, Dumh: REAL;
  200.   BEGIN keySum := keys; x := x - f.X; i := 1; backUp := f.col;
  201.     WHILE (i <= Comp) & (f.beg[i] < x) DO INC(i) END;
  202.     IF i <= Comp THEN DEC(i); last := -1;
  203.       REPEAT Input.Mouse(keys, x, y); keySum := keySum + keys;
  204.         Oberon.DrawCursor(Oberon.Mouse, Oberon.Mouse.marker, x, y); y := y - f.Y;
  205.         IF y < 0 THEN y := 0 ELSIF y > f.H THEN y := f.H END;
  206.         AmigaMath.IntToReal(y, Dumy);
  207.         AmigaMath.IntToReal(f.H, Dumh);
  208.         AmigaMath.Div(Dumy, Dumh, f.col.hls[i]);
  209.         (* f.col.hls[i] := y / f.H;*)
  210.         IF AmigaMath.Cmp(f.col.hls[i], last)#0 THEN
  211.         (* IF f.col.hls[i] # last THEN*)
  212.           UpdateRGB(f.col); UpdateDisp(f.col); last := f.col.hls[i];
  213.           Oberon.RemoveMarks(f.X, f.Y, f.W, f.H);
  214.           Display.ReplPattern(Display.white, grey[(i MOD 2) * 2], f.X + f.beg[i], f.Y, f.beg[i + 1] - f.beg[i] , y, Display.replace);
  215.           Display.ReplConst(Display.black, f.X + f.beg[i], f.Y + y, f.beg[i + 1] - f.beg[i] , f.H - y, Display.replace);
  216.           Viewers.Broadcast(m)
  217.         END
  218.       UNTIL keys = {};
  219.       IF (keySum # {Left}) OR (f.col.nr > 0) & (f.col.nr < 4) THEN f.col := backUp; UpdateDisp(backUp); ShowHLS(f) END
  220.     END
  221.   END EditHLS;
  222.   PROCEDURE HandleEdit(f: Display.Frame; VAR m: Display.FrameMsg);
  223.     VAR frame: EditFrame;
  224.   BEGIN
  225.     WITH f: EditFrame DO
  226.       IF m IS Oberon.InputMsg THEN
  227.         WITH m: Oberon.InputMsg DO
  228.           IF m.id = Oberon.track THEN
  229.             IF m.keys = {} THEN Oberon.DrawCursor(Oberon.Mouse, Oberon.Mouse.marker, m.X, m.Y)
  230.             ELSIF f.rgb THEN EditRGB(f, m.X, m.Y, m.keys)
  231.             ELSE EditHLS(f, m.X, m.Y, m.keys)
  232.             END
  233.           END
  234.         END
  235.       ELSIF (m IS Msg) & Change(f.col) THEN
  236.         IF f.rgb THEN ShowRGB(f) ELSE ShowHLS(f) END
  237.       ELSIF m IS Oberon.CopyMsg THEN NEW(frame); frame^ := f^; m(Oberon.CopyMsg).F := frame
  238.       ELSIF m IS MenuViewers.ModifyMsg THEN
  239.         WITH m: MenuViewers.ModifyMsg DO f.Y := m.Y; f.H := m.H;
  240.           IF f.rgb THEN ShowRGB(f) ELSE ShowHLS(f) END
  241.         END
  242.       END
  243.     END
  244.   END HandleEdit;
  245.   PROCEDURE EditColor(colNr: INTEGER; rgb: BOOLEAN);
  246.     VAR f: EditFrame;  v: Viewers.Viewer;  col: Color;  x, y: INTEGER; dummy: BOOLEAN;
  247.   BEGIN col.nr := colNr; (* col.rgb[0] := -1; col.rgb[1] := -1; col.rgb[2] := -1; *) dummy := Change(col);    (* << RC *)
  248.     NEW(f); f.col := col; f.handle := HandleEdit; f.rgb := rgb; Oberon.AllocateSystemViewer(Oberon.Mouse.X, x, y);
  249.     v := MenuViewers.New(TextFrames.NewMenu("Color", Menu), f, TextFrames.menuH, x, y);
  250.     Texts.Write(w, " "); Texts.WriteInt(w, colNr, 0); Texts.Insert(v.dsc(TextFrames.Frame).text, 5, w.buf)
  251.   END EditColor;
  252.   PROCEDURE Show(f: Frame);
  253.     VAR i, r, n, w, x: INTEGER;
  254.   BEGIN n := f.n; w := f.W DIV n; r := f.W - w * n; i := 0; x := 0; INC(w);
  255.     WHILE i < n DO f.beg[i] := x;
  256.       IF r = 0 THEN DEC(w) END;
  257.       Display.ReplConst(i, f.X + x, f.Y, w, f.H, Display.replace); INC(x, w); INC(i); DEC(r)
  258.     END
  259.   END Show;
  260.   PROCEDURE Edit(f: Frame; x, y: INTEGER; keys: SET);
  261.     VAR keySum: SET; i: INTEGER;
  262.   BEGIN keySum := keys;
  263.     REPEAT Input.Mouse(keys, x, y); keySum := keySum + keys;
  264.       Oberon.DrawCursor(Oberon.Mouse, Oberon.Mouse.marker, x, y)
  265.     UNTIL keys = {};
  266.     IF (keySum = {Left}) OR (keySum = {Right}) THEN i := 1; x := x - f.X;
  267.       WHILE (i < f.n) & (f.beg[i] < x) DO INC(i) END;
  268.       EditColor(i-1, keySum = {Left})
  269.     END
  270.   END Edit;
  271.   PROCEDURE Handler(f: Display.Frame; VAR m: Display.FrameMsg);
  272.     VAR frame: Frame;
  273.   BEGIN
  274.     WITH f: Frame DO
  275.       IF m IS Oberon.InputMsg THEN
  276.         WITH m: Oberon.InputMsg DO
  277.           IF m.id = Oberon.track THEN
  278.             IF m.keys = {} THEN Oberon.DrawCursor(Oberon.Mouse, Oberon.Mouse.marker, m.X, m.Y)
  279.             ELSE Edit(f, m.X, m.Y, m.keys)
  280.             END
  281.           END
  282.         END
  283.       ELSIF m IS Oberon.CopyMsg THEN NEW(frame); frame^ := f^; m(Oberon.CopyMsg).F := frame
  284.       ELSIF m IS MenuViewers.ModifyMsg THEN
  285.         WITH m: MenuViewers.ModifyMsg DO f.Y := m.Y; f.H := m.H; Show(f) END
  286.       END
  287.     END
  288.   END Handler;
  289.   PROCEDURE Open*;
  290.     VAR s: Texts.Scanner;  f: Frame; v: Viewers.Viewer;  x, y, n: INTEGER;
  291.   BEGIN Texts.OpenScanner(s, Oberon.Par.text, Oberon.Par.pos); Texts.Scan(s);
  292.     IF s.class = Texts.Int THEN n := SHORT(s.i) ELSE n := Cols END;
  293.     Oberon.AllocateSystemViewer(Oberon.Mouse.X, x, y); NEW(f); f.handle := Handler; f.n := n;
  294.     v := MenuViewers.New(TextFrames.NewMenu("Colors", Menu), f, TextFrames.menuH, x, y)
  295.   END Open;
  296.     PROCEDURE Scan(VAR s: Texts.Scanner);
  297.         VAR T: Texts.Text;
  298.              beg, end, time: LONGINT;
  299.     BEGIN
  300.         Texts.OpenScanner(s, Oberon.Par.text, Oberon.Par.pos); Texts.Scan(s);
  301.         IF (s.class = Texts.Char) & (s.c = "^") OR (s.line # 0) THEN
  302.             Oberon.GetSelection(T, beg, end, time);
  303.             IF time >= 0 THEN Texts.OpenScanner(s, T, beg); Texts.Scan(s) END
  304.         END
  305.     END Scan;
  306.   PROCEDURE OpenRGB*;
  307.     VAR s: Texts.Scanner;
  308.   BEGIN Scan(s);
  309.     IF s.class = Texts.Int THEN EditColor(SHORT(s.i), TRUE) END
  310.   END OpenRGB;
  311.   PROCEDURE OpenHLS*;
  312.     VAR s: Texts.Scanner;
  313.   BEGIN Scan(s);
  314.     IF s.class = Texts.Int THEN EditColor(SHORT(s.i), FALSE) END
  315.   END OpenHLS;
  316.   PROCEDURE Set*;
  317.     VAR s: Texts.Scanner;  v: ARRAY 4 OF INTEGER; i: INTEGER;
  318.   BEGIN Scan(s); i := 0;
  319.     WHILE (s.class = Texts.Int) & (i < 4) DO v[i] := SHORT(s.i); Texts.Scan(s); INC(i) END;
  320.     IF i = 4 THEN Display.SetColor(v[0], v[1], v[2], v[3]) END
  321.   END Set;
  322.   PROCEDURE Get*;
  323.     VAR s: Texts.Scanner;  v: ARRAY 4 OF INTEGER; i: INTEGER;
  324.   BEGIN Scan(s);
  325.     IF s.class = Texts.Int THEN v[0] := SHORT(s.i); Display.GetColor(v[0], v[1], v[2], v[3]); i := 0;
  326.       WHILE i < 4 DO Texts.WriteInt(w, v[i], 5); INC(i) END;
  327.       Texts.WriteLn(w); Texts.Append(Oberon.Log, w.buf)
  328.     END
  329.   END Get;
  330.     PROCEDURE Load*;
  331.       VAR par: Oberon.ParList;
  332.         S: Texts.Scanner;
  333.         f: Files.File; R: Files.Rider;
  334.         col: SHORTINT; red, green, blue: CHAR;
  335.     BEGIN
  336.       Texts.WriteString(w, "Colors.Load ");
  337.       par := Oberon.Par;
  338.       Texts.OpenScanner(S, par.text, par.pos); Texts.Scan(S);
  339.       IF S.class = Texts.Name THEN
  340.         Texts.WriteString(w, S.s);
  341.         f := Files.Old(S.s);
  342.         IF f # NIL THEN
  343.           Files.Set(R, f, 0); col := -1;
  344.           REPEAT
  345.             Files.Read(R, red); Files.Read(R, green); Files.Read(R, blue);
  346.             Display.SetColor(col, ORD(red), ORD(green), ORD(blue));
  347.             INC(col)
  348.           UNTIL col = 16
  349.         ELSE Texts.WriteString(w, " not found")
  350.         END
  351.       ELSE Texts.WriteString(w, " no name")
  352.       END;
  353.       Texts.WriteLn(w);
  354.       Texts.Append(Oberon.Log, w.buf)
  355.     END Load;
  356.     PROCEDURE Store*;
  357.       VAR par: Oberon.ParList;
  358.         S: Texts.Scanner;
  359.         f: Files.File; R: Files.Rider;
  360.         col, red, green, blue: INTEGER;
  361.     BEGIN
  362.       Texts.WriteString(w, "Colors.Store ");
  363.       par := Oberon.Par;
  364.       Texts.OpenScanner(S, par.text, par.pos); Texts.Scan(S);
  365.       IF S.class = Texts.Name THEN
  366.         Texts.WriteString(w, S.s);
  367.         f := Files.New(S.s); Files.Set(R, f, 0);
  368.         IF f # NIL THEN col := -1;
  369.           REPEAT
  370.            Display.GetColor(col, red, green, blue);
  371.            Files.Write(R, CHR(red));
  372.            Files.Write(R, CHR(green));
  373.            Files.Write(R, CHR(blue));
  374.            INC(col)
  375.           UNTIL col = 16;
  376.           Files.Register(f)
  377.         ELSE Texts.WriteString(w, " no space")
  378.         END
  379.       ELSE Texts.WriteString(w, " no name")
  380.       END;
  381.       Texts.WriteLn(w);
  382.       Texts.Append(Oberon.Log, w.buf)
  383.     END Store;
  384.   PROCEDURE* Activate;
  385.     VAR m: Msg;
  386.   BEGIN Viewers.Broadcast(m)
  387.   END Activate;
  388. BEGIN 
  389.   Cols:=SHORT(ASH(1, Amiga.OberonDepth));
  390.   Texts.OpenWriter(w);
  391.   NEW(task); task.handle := Activate; task.safe := FALSE; task.time := -1; Oberon.Install(task);
  392.   grey[0] := Display.grey0; grey[1] := Display.grey1; grey[2] := Display.grey2
  393. END Colors.
  394. Colors.Open
  395. Colors.Set ^
  396.   1 255 0 0 ~ 2 0 255 0 ~ 3 0 0 255 ~
  397. Colors.Get ^  Colors.OpenRGB ^  Colors.OpenHLS ^
  398.   0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
  399.