-- File: ClockAlto.mesa,  Last Edit: HGM  May 30, 1980  10:21 AM

DIRECTORY
  InlineDefs USING [MesaToBcplLongNumber],
  OsStaticDefs USING [OsStatics],
  Process USING [Detach],
  System USING [GreenwichMeanTime],
  TimeDefs USING [currentTime, currentParameters],
  Clock USING [TimeParameters];

ClockAlto: PROGRAM IMPORTS InlineDefs, Process EXPORTS Clock SHARES TimeDefs =
  BEGIN

  timeIsOk: BOOLEAN ← FALSE;

  TimeIsKnown: PUBLIC PROCEDURE RETURNS [BOOLEAN] = BEGIN RETURN[timeIsOk]; END;

  verbose: BOOLEAN = TRUE;

  SetTime: PUBLIC PROCEDURE [t: System.GreenwichMeanTime] =
    BEGIN
    TimeDefs.currentTime↑ ← InlineDefs.MesaToBcplLongNumber[t];
    timeIsOk ← TRUE;
    END;

  correction: INTEGER ← 0;

  -- Seconds per day, + for faster
  SetCorrection: PUBLIC PROCEDURE [seconds: INTEGER] =
    BEGIN
    ticks: LONG INTEGER ← 1680000; -- beware of double corrections
    -- + correction makes clock go faster by needing fewer ticks to get to a second
    ticks ← ticks - 19*LONG[seconds]; -- 1680000/86400 is 19.44
    OsStaticDefs.OsStatics.ClockSecond↑ ← InlineDefs.MesaToBcplLongNumber[ticks];
    correction ← seconds;
    END;

  GetCorrection: PUBLIC PROCEDURE RETURNS [INTEGER] =
    BEGIN RETURN[correction]; END;

  SetTimeParms: PUBLIC PROCEDURE [t: Clock.TimeParameters] =
    BEGIN
    TimeDefs.currentParameters.direction ← IF t.zone > 0 THEN west ELSE east;
    TimeDefs.currentParameters.zone ← ABS[t.zone];
    TimeDefs.currentParameters.zoneminutes ← t.minutes;
    TimeDefs.currentParameters.beginDST ← t.beginDst;
    TimeDefs.currentParameters.endDST ← t.endDst;
    END;

  GetTimeParms: PUBLIC PROCEDURE RETURNS [Clock.TimeParameters] =
    BEGIN
    RETURN[
      [zone:
       IF TimeDefs.currentParameters.direction = west THEN
       TimeDefs.currentParameters.zone ELSE -TimeDefs.currentParameters.zone,
	minutes: TimeDefs.currentParameters.zoneminutes,
	beginDst: TimeDefs.currentParameters.beginDST,
	endDst: TimeDefs.currentParameters.endDST]];
    END;


  -- The clock drifts if an EIA board is running while the display is on.

  resetter: PROCEDURE ← BEGIN END;

  DisplayGoingOn: PUBLIC PROCEDURE = BEGIN timeIsOk ← FALSE; END;

  DisplayGoingOff: PUBLIC PROCEDURE = BEGIN Process.Detach[FORK resetter[]]; END;

  SetTimeResetter: PUBLIC PROCEDURE [proc: PROCEDURE] =
    BEGIN resetter ← proc; END;

  END.