(*---------------------------------------------------------------------------
  :Program.     OClock.mod
  :Contents.    Nice little analog clock
  :Author.      Christian Stiens
  :Address.     Heustiege 2, W-4710 Lüdinghausen
  :Copyright.   PD
  :Language.    Oberon
  :Translator.  Amiga Oberon V2.01 [fbs]
  :History.     V1.0, 24-Jul-91
---------------------------------------------------------------------------*)


MODULE OClock;

  (* $RangeChk- $NilChk- $StackChk- $OvflChk- $ReturnChk- $CaseChk- *)

  IMPORT
    I: Intuition,
    e: Exec,
    d: Dos,
    g: Graphics,
    s: SYSTEM;

  CONST
    esc = 69;

  VAR
    nw         : I.NewWindow;
    win        : I.WindowPtr;
    rp         : g.RastPortPtr;
    im         : I.Image;
    msg        : I.IntuiMessagePtr;
    dragGad    : I.Gadget;
    oldMin     : INTEGER;
    x0,y0      : INTEGER;
    i          : INTEGER;
    hlx,mlx    : INTEGER;
    hly,mly    : INTEGER;

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

  CONST
    width   = 90;
    height  = 45;
    depth   = 2;

  TYPE
    IntArray540 = ARRAY 540 OF INTEGER;

  (* $DataChip+ *)

  CONST OClockData = IntArray540(
    00000U,00000U,01FFFU,0FE00U,00000U,00000U,
    00000U,00007U,0F000U,003F8U,00000U,00000U,
    00000U,000FCU,00063U,0C00FU,0C000U,00000U,
    00000U,00780U,00066U,06000U,07800U,00000U,
    00000U,03C00U,00060U,0C000U,00F00U,00000U,
    00001U,0E060U,00063U,08001U,081E0U,00000U,
    00007U,000F0U,00067U,0E003U,0C038U,00000U,
    0001CU,00060U,00000U,00001U,0800EU,00000U,
    00030U,00000U,00000U,00000U,00003U,00000U,
    000E0U,00000U,00000U,00000U,00001U,0C000U,
    00180U,00000U,00000U,00000U,00000U,06000U,
    00300U,00000U,00000U,00000U,00000U,03000U,
    00618U,00000U,00000U,00000U,00006U,01800U,
    00C3CU,00000U,00000U,00000U,0000FU,00C00U,
    01818U,00000U,00000U,00000U,00006U,00600U,
    03000U,00000U,00000U,00000U,00000U,00300U,
    03000U,00000U,00000U,00000U,00000U,00300U,
    06000U,00000U,00000U,00000U,00000U,00180U,
    06000U,00000U,00000U,00000U,00000U,00180U,
    0C000U,00000U,00000U,00000U,00000U,000C0U,
    0C3E0U,00000U,00000U,00000U,00001U,0F0C0U,
    0C630U,00000U,00006U,00000U,00000U,018C0U,
    0C3F0U,00000U,0000FU,00000U,00000U,0F0C0U,
    0C030U,00000U,00006U,00000U,00000U,018C0U,
    0C3E0U,00000U,00000U,00000U,00001U,0F0C0U,
    0C000U,00000U,00000U,00000U,00000U,000C0U,
    06000U,00000U,00000U,00000U,00000U,00180U,
    06000U,00000U,00000U,00000U,00000U,00180U,
    03000U,00000U,00000U,00000U,00000U,00300U,
    03000U,00000U,00000U,00000U,00000U,00300U,
    01818U,00000U,00000U,00000U,00006U,00600U,
    00C3CU,00000U,00000U,00000U,0000FU,00C00U,
    00618U,00000U,00000U,00000U,00006U,01800U,
    00300U,00000U,00000U,00000U,00000U,03000U,
    00180U,00000U,00000U,00000U,00000U,06000U,
    000E0U,00000U,00000U,00000U,00001U,0C000U,
    00030U,00000U,00000U,00000U,00003U,00000U,
    0001CU,00030U,00000U,00003U,0000EU,00000U,
    00007U,00078U,0001FU,00007U,08038U,00000U,
    00001U,0E030U,00030U,00003U,001E0U,00000U,
    00000U,03C00U,0003FU,00000U,00F00U,00000U,
    00000U,00780U,00031U,08000U,07800U,00000U,
    00000U,000FCU,0001FU,0000FU,0C000U,00000U,
    00000U,00007U,0F000U,003F8U,00000U,00000U,
    00000U,00000U,01FFFU,0FE00U,00000U,00000U,
    00000U,00000U,00000U,00000U,00000U,00000U,
    00000U,00000U,00FFFU,0FC00U,00000U,00000U,
    00000U,00003U,0FF9CU,03FF0U,00000U,00000U,
    00000U,0007FU,0FF99U,09FFFU,08000U,00000U,
    00000U,003FFU,0FF9FU,03FFFU,0F000U,00000U,
    00000U,01FDFU,0FF9CU,07FFFU,07E00U,00000U,
    00000U,0FFCFU,0FF98U,01FFFU,03FC0U,00000U,
    00003U,0FFDFU,0FFFFU,0FFFFU,07FF0U,00000U,
    0000FU,0FFFFU,0FFFFU,0FFFFU,0FFFCU,00000U,
    0001FU,0FFFFU,0FFFFU,0FFFFU,0FFFEU,00000U,
    0007FU,0FFFFU,0FFFFU,0FFFFU,0FFFFU,08000U,
    000FFU,0FFFFU,0FFFFU,0FFFFU,0FFFFU,0C000U,
    001F7U,0FFFFU,0FFFFU,0FFFFU,0FFFDU,0E000U,
    003F3U,0FFF0U,0E13EU,01C24U,0FFFCU,0F000U,
    007F7U,0FFE6U,04F3CU,0C9E3U,0FFFDU,0F800U,
    00FFFU,0FFE6U,04F3CU,0C9E1U,0FFFFU,0FC00U,
    00FFFU,0FFF0U,0E106U,01C24U,0FFFFU,0FC00U,
    01FFFU,0FFFFU,0FFFFU,0FFFFU,0FFFFU,0FE00U,
    01FFFU,0FFFFU,0FFFFU,0FFFFU,0FFFFU,0FE00U,
    03FFFU,0FFFFU,0FFFFU,0FFFFU,0FFFFU,0FF00U,
    03C1FU,0FFFFU,0FFFFU,0FFFFU,0FFFEU,00F00U,
    039CFU,0FFFFU,0FFF9U,0FFFFU,0FFFFU,0E700U,
    03C0FU,0FFFFU,0FFF0U,0FFFFU,0FFFFU,00F00U,
    03FCFU,0FFFFU,0FFF9U,0FFFFU,0FFFFU,0E700U,
    03C1FU,0FFFFU,0FFFFU,0FFFFU,0FFFEU,00F00U,
    03FFFU,0FFFFU,0FFFFU,0FFFFU,0FFFFU,0FF00U,
    01FFFU,0FFFFU,0FFFFU,0FFFFU,0FFFFU,0FE00U,
    01FFFU,0FFFFU,0FFFFU,0FFFFU,0FFFFU,0FE00U,
    00FFFU,0FFFFU,0FFFFU,0FFFFU,0FFFFU,0FC00U,
    00FFFU,0FFFFU,0FFFFU,0FFFFU,0FFFFU,0FC00U,
    007F7U,0FFFFU,0FFFFU,0FFFFU,0FFFDU,0F800U,
    003F3U,0FFFFU,0FFFFU,0FFFFU,0FFFCU,0F000U,
    001F7U,0FFFFU,0FFFFU,0FFFFU,0FFFDU,0E000U,
    000FFU,0FFFFU,0FFFFU,0FFFFU,0FFFFU,0C000U,
    0007FU,0FFFFU,0FFFFU,0FFFFU,0FFFFU,08000U,
    0001FU,0FFFFU,0FFFFU,0FFFFU,0FFFEU,00000U,
    0000FU,0FFFFU,0FFFFU,0FFFFU,0FFFCU,00000U,
    00003U,0FFEFU,0FFFFU,0FFFEU,0FFF0U,00000U,
    00000U,0FFE7U,0FFE0U,0FFFEU,07FC0U,00000U,
    00000U,01FEFU,0FFCFU,0FFFEU,0FE00U,00000U,
    00000U,003FFU,0FFC0U,0FFFFU,0F000U,00000U,
    00000U,0007FU,0FFCEU,07FFFU,08000U,00000U,
    00000U,00003U,0FFE0U,0FFF0U,00000U,00000U,
    00000U,00000U,00FFFU,0FC00U,00000U,00000U,
    00000U,00000U,00000U,00000U,00000U,00000U);

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

  TYPE
    Arr60 = ARRAY 60 OF SHORTINT;

  CONST
    sinTab = Arr60(0,13,26,39,52,63,75,85,94,103,110,116,121,124,126,127,126,
                 124,121,116,110,103,94,85,75,64,52,39,26,13,0,-13,-26,-39,
                 -52,-63,-75,-85,-94,-103,-110,-116,-121,-124,-126,-127,-126,
                 -124,-121,-116,-110,-103,-94,-85,-75,-64,-52,-39,-26,-13);

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

  PROCEDURE DrawZeiger(min,lx,ly: INTEGER);
    VAR zx,zy : INTEGER;
        si,co : INTEGER;
  BEGIN
    si := sinTab[min];
    co := sinTab[(min+15) MOD 60];
    zx := lx * si DIV 128;
    zy := ly * co DIV 128;
    g.SetAPen(rp,1);
    g.Move(rp,x0,y0);
    g.Draw(rp,x0+zx,y0-zy);
    g.Move(rp,x0+1,y0);
    g.Draw(rp,x0+zx+1,y0-zy);
  END DrawZeiger;

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

  PROCEDURE ShowClock;
    VAR hour,min: INTEGER;
        sec,mic,day : LONGINT;
  BEGIN
    I.CurrentTime(sec,mic);
    sec := sec MOD 86400;
    min := SHORT((sec MOD 3600) DIV 60);
    IF min # oldMin THEN
      hour := SHORT((sec DIV 720) MOD 60);
      I.DrawImage(rp,im,0,0);
      DrawZeiger(hour,hlx,hly);
      DrawZeiger(min,mlx,mly);
      oldMin := min;
    END;
  END ShowClock;

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

BEGIN

  oldMin := -1;

  im.width     := width;
  im.height    := height;
  im.depth     := depth;
  im.imageData := s.ADR(OClockData);
  im.planePick := SHORTSET{0,1};

  dragGad.flags      := {I.gRelWidth,I.gRelHeight} + I.gadgHNone;
  dragGad.gadgetType := I.wDragging;
  dragGad.activation := {I.gadgImmediate};

  nw.leftEdge    := 50;
  nw.topEdge     := 30;
  nw.flags       := LONGSET{I.borderless};
  nw.idcmpFlags  := LONGSET{I.rawKey};
  nw.type        := {I.wbenchScreen};
  nw.width       := width;
  nw.height      := height;
  nw.firstGadget := s.ADR(dragGad);

  win := I.OpenWindow(nw);
  IF win = NIL THEN HALT(20) END;

  rp := win.rPort;

  x0 := width DIV 2; y0 := height DIV 2;
  hlx := (width * 16) DIV 55; mlx := (width * 16) DIV 40;
  hly := (height* 16) DIV 55; mly := (height* 16) DIV 40;

  LOOP
    ShowClock;
    msg := e.GetMsg(win.userPort);
    WHILE msg # NIL DO
      IF (I.rawKey IN msg.class) & (msg.code = esc) THEN
        e.ReplyMsg(msg); HALT(0)
      END;
      e.ReplyMsg(msg);
      msg := e.GetMsg(win.userPort);
    END;
    d.Delay(d.ticksPerSecond);
  END;

CLOSE

  IF win # NIL THEN I.CloseWindow(win) END;

END OClock.

