(*
  :Program.       Hilbert
  :Author.        Volker Rudolph
  :Address.       Lettow-Vorbeck-Str. 11 / 6750 Kaiserslautern 26
  :Phone.         06301/8566
  :Version.       1.0
  :Date.          23.7.90
  :Copyright.     PD
  :Language.      Oberon (Freeware)
  :Translator.    Amiga-Oberon V1.14
  :Contents.      Zeichnet Hilbert-Kurven
*)

MODULE Hilbert;

IMPORT e:Exec,i:Intuition,g:Graphics,Break,n:NoGuru,s:SYSTEM;

CONST
  ScreenWidth = 350;
  ScreenHeight = 282;
  SquareSize = 256;

VAR
  sc:i.ScreenPtr;
  wi:i.WindowPtr;
  msg:e.MsgPortPtr;

(* -------------------------------------------------------------------------- *)

PROCEDURE WaitForClick;
BEGIN
  e.WaitPort(wi.userPort);
  msg := e.GetMsg(wi.userPort);
  e.WaitPort(wi.userPort);
  msg := e.GetMsg(wi.userPort);
END WaitForClick;

PROCEDURE CreateGraphics;
VAR
  ns:i.NewScreen;
  nw:i.NewWindow;
BEGIN
  ns.leftEdge := 0;
  ns.topEdge := 0;
  ns.width := ScreenWidth;
  ns.height := ScreenHeight;
  ns.depth := 3;
  ns.detailPen := 1;
  ns.blockPen := 2;
  ns.viewModes := {};
  ns.type := i.customScreen;
  ns.font := NIL;
  ns.defaultTitle := NIL;
  ns.gadgets := NIL;
  ns.customBitMap := NIL;
  sc := i.OpenScreen(ns);
  n.Assert(sc # NIL,"Can't open screen");

  nw.leftEdge := 0;
  nw.topEdge := 0;
  nw.width := ScreenWidth;
  nw.height := ScreenHeight;
  nw.detailPen := 1;
  nw.blockPen := 2;
  nw.idcmpFlags := LONGSET{i.mouseButtons};
  nw.flags := LONGSET{i.borderless};
  nw.firstGadget := NIL;
  nw.checkMark := NIL;
  nw.title := NIL;
  nw.screen := sc;
  nw.bitMap := NIL;
  nw.minWidth := 0;
  nw.minHeight := 0;
  nw.maxWidth := ScreenHeight;
  nw.maxHeight := ScreenHeight;
  nw.type := i.customScreen;
  wi := i.OpenWindow(nw);
  n.Assert(wi # NIL,"Can't open window");
  g.SetRGB4(s.ADR(sc.viewPort),2,15,15,0);
END CreateGraphics;

PROCEDURE RemoveGraphics;
BEGIN
  IF wi # NIL THEN
    i.CloseWindow(wi);
    wi := NIL;
  END; (* IF *)
  IF sc # NIL THEN
    i.CloseScreen(sc);
    sc := NIL;
  END; (* IF *)
END RemoveGraphics;

PROCEDURE Line(direction,delta:INTEGER);
BEGIN
  CASE direction OF
    0:g.Draw(wi.rPort,wi.rPort.x+delta,wi.rPort.y);
   |2:g.Draw(wi.rPort,wi.rPort.x,wi.rPort.y-delta);
   |4:g.Draw(wi.rPort,wi.rPort.x-delta,wi.rPort.y);
   |6:g.Draw(wi.rPort,wi.rPort.x,wi.rPort.y+delta);
  ELSE
    n.Assert(FALSE,"Wrong direction");
  END; (* CASE *)
END Line;

(* -------------------------------------------------------------------------- *)

PROCEDURE Hilbert;
VAR
  i,x0,y0,u:INTEGER;

  PROCEDURE ^A(i:INTEGER);
  PROCEDURE ^B(i:INTEGER);
  PROCEDURE ^C(i:INTEGER);
  PROCEDURE ^D(i:INTEGER);

  PROCEDURE A(i:INTEGER);
  BEGIN
    IF i > 0 THEN
      D(i-1); Line(4,u);
      A(i-1); Line(6,u);
      A(i-1); Line(0,u);
      B(i-1);
    END; (* IF *)
  END A;

  PROCEDURE B(i:INTEGER);
  BEGIN
    IF i > 0 THEN
      C(i-1); Line(2,u);
      B(i-1); Line(0,u);
      B(i-1); Line(6,u);
      A(i-1);
    END; (* IF *)
  END B;

  PROCEDURE C(i:INTEGER);
  BEGIN
    IF i > 0 THEN
      B(i-1); Line(0,u);
      C(i-1); Line(2,u);
      C(i-1); Line(4,u);
      D(i-1);
    END; (* IF *)
  END C;

  PROCEDURE D(i:INTEGER);
  BEGIN
    IF i > 0 THEN
      A(i-1); Line(6,u);
      D(i-1); Line(4,u);
      D(i-1); Line(2,u);
      C(i-1);
    END; (* IF *)
  END D;

BEGIN
  x0 := ScreenWidth DIV 2;
  y0 := ScreenHeight DIV 2;
  u := SquareSize;
  i := 0;
  REPEAT
    INC(i);
    u := u DIV 2;
    x0 := x0 + (u DIV 2);
    y0 := y0 + (u DIV 2);
    g.SetAPen(wi.rPort,i);
    g.Move(wi.rPort,x0,ScreenHeight-y0);
    A(i);
    (* WaitForClick; *)
  UNTIL (i = 6);
END Hilbert;

(* -------------------------------------------------------------------------- *)

BEGIN
  CreateGraphics;
  Hilbert;
  WaitForClick;
CLOSE
  RemoveGraphics;
END Hilbert.
