-- Copyright (C) 1980, 1981, 1984  by Xerox Corporation. All rights reserved. 
-- File: LogDisplayCold.mesa

-- HGM, 18-Nov-84  0:50:33
-- Pilot version 30-Jul-81 17:08:31

DIRECTORY
  LogDefs USING [defaultRefreshInterval, DisplayItem, Percentage, WriteLine, WriteLogEntry],
  LogPrivateDefs USING [
    Displayer, houses, IllegalUseOfLog, LogDisplayHot, NumberHouseObject,
    startUpTime, typescriptOn, tty, uptimeHouse],
  Process USING [Abort, Seconds],
  Runtime USING [GetBcdTime],
  String USING [AppendChar, AppendLongDecimal, AppendString],
  Storage USING [Node, String, Free],
  Time USING [Append, Current, Unpack],
  TTY USING [Create];

LogDisplayCold: MONITOR
  IMPORTS
    LogDefs, LogPrivateDefs, Process, Runtime, String, ShortTermHeap: Storage,
    LongTermHeap: Storage, Time, TTY
  EXPORTS LogDefs =
  BEGIN OPEN LogDefs, LogPrivateDefs;
  -- Types and Related Constants --
  RegisteredValueObject: TYPE = --MACHINE DEPENDENT-- RECORD [
    link: RegisteredValue, item: DisplayItem, caption: StringBody];
  RegisteredValue: TYPE = POINTER TO RegisteredValueObject;

  -- Global Variables --

  firstValue, lastValue: RegisteredValue;
  nValues: CARDINAL;
  statisticsOn: BOOLEAN;  -- typescriptOn in LogDisplayHot
  statusString: STRING;
  displayProcess: PROCESS;
  statsRefreshInterval: Process.Seconds;

  -- Miscellaneous Declarations --

  daytimeLength: CARDINAL = 18;  -- length of:  12-Jan-80 14:35:52
  fullDaytimeLength: CARDINAL = 22;  -- length of:  12-Jan-80 14:35:52 PST
  elapsedTimeLength: CARDINAL = 13;  -- length of:  1234567:35:28

  -- Start/Stop Procedures --

  StatisticsOn: PUBLIC ENTRY PROCEDURE [heading: STRING] =
    -- Called after all statistics specification procedures (SetStatisticsParameters and DisplayNumber) have been called.  'heading' is an ASCII string that will be displayed at the top of the screen.  The 'heading' string need not persist in the client's storage after DisplayOn has returned.  StatisticsOn concludes with an implicit ScreenOn.
    BEGIN
    BuildStatusString: PROCEDURE =
      -- sets up the status string and variables required to refresh it.
      BEGIN OPEN String, Time;
      s1: STRING = "Version of "L;
      s2: STRING = "  Up at "L;
      s3: STRING = "  Uptime: "L;
      length: CARDINAL =
        s1.length + daytimeLength + s2.length + fullDaytimeLength + s3.length +
          elapsedTimeLength;
      startUpTime ← Current[];
      statusString ← LongTermHeap.String[length];
      AppendString[statusString, s1];
      Append[statusString, Unpack[Runtime.GetBcdTime[]]];
      AppendString[statusString, s2];
      Append[statusString, Unpack[startUpTime], TRUE];
      AppendString[statusString, s3];
      uptimeHouse ← NumberHouseObject[caption: statusString, item:];
      END;  -- BuildStatusString
    BuildHouses: PROCEDURE =
      -- Constructs the statistics data structures.
      BEGIN
      h: CARDINAL;
      val: RegisteredValue;
      houses ← DESCRIPTOR[
        LongTermHeap.Node[nValues * SIZE[NumberHouseObject]], nValues];
      FOR h IN [0..nValues) DO
        houses[h] ← NumberHouseObject[
          caption: LongTermHeap.String[firstValue.caption.length], item:];
        String.AppendString[houses[h].caption, @(firstValue.caption)];
        WITH val: firstValue.item SELECT FROM
          short =>
            houses[h].item ← short[
              max: FIRST[CARDINAL], min: LAST[CARDINAL], p: val.p];
          long =>
            houses[h].item ← long[
              max: FIRST[LONG CARDINAL], min: LAST[LONG CARDINAL], p: val.p];
          percent =>
            houses[h].item ← percent[
              max: FIRST[Percentage], min: LAST[Percentage], p: val.p];
          ENDCASE;
        val ← firstValue.link;
        ShortTermHeap.Free[firstValue];
        firstValue ← val;
        ENDLOOP;
      END;  -- BuildHouses
    IF statisticsOn THEN ERROR IllegalUseOfLog;
    BuildStatusString[];
    BuildHouses[];
    statisticsOn ← TRUE;
    displayProcess ← FORK Displayer[statsRefreshInterval];
    END;  --DisplayOn

  TypescriptOn: PUBLIC ENTRY PROCEDURE =
    -- called after the typescript specification procedure (SetTypescriptParameters) has been called.  The typescript is initialized and made ready for calls on WriteChar, WriteString, and related output procedures.  TypescriptOn concludes with an implicit ScreenOn.
    BEGIN IF typescriptOn THEN ERROR IllegalUseOfLog; typescriptOn ← TRUE; END;  --TypescriptOn

  DisplayOff: PUBLIC ENTRY PROCEDURE =
    -- DisplayOff first performs an implicit ScreenOff, then causes an orderly cleanup of the display data structures.  All information previously supplied via SetStatisticsParameters, DisplayNumber, and SetTypescriptParameters is discarded and all internal data structures are released.
    BEGIN
    IF statisticsOn THEN
      BEGIN Process.Abort[displayProcess]; LongTermHeap.Free[BASE[houses]]; END;
    IF typescriptOn THEN NULL;  --Turn Off TTY??
    Initialize[];
    END;  --DisplayOff

  ScreenOff: PUBLIC ENTRY PROCEDURE =
    -- turns off the display screen without affecting any of the underlying data structures.
    BEGIN END;  --ScreenOff

  ScreenOn: PUBLIC ENTRY PROCEDURE =
    -- undoes the effect of ScreenOff.
    BEGIN END;  --ScreenOn
  -- Statistics Display Procedures --

  SetStatisticsParameters: PUBLIC ENTRY PROCEDURE [
    bmPages: CARDINAL, font: STRING ← NIL,
    refreshInterval: Process.Seconds ← defaultRefreshInterval] =
    -- This procedure alters the defaults for the statistics region of the display.  This procedure, if called at all, must be called before StatisticsOn.
    BEGIN
    IF statisticsOn THEN ERROR IllegalUseOfLog;
    statsRefreshInterval ← refreshInterval;
    END;  --SetStatisticsParameters

  DisplayNumber: PUBLIC ENTRY PROCEDURE [caption: STRING, item: DisplayItem] =
    -- Registers a value to be maintained on the display. The 'item' defines the main memory location of the value (which must not move) and the format in which it is to be displayed.  The 'caption' is accompanying ASCII text.  The 'caption' string need not persist in the client's storage after DisplayNumber has returned.  DisplayNumber must be called before StatisticsOn.
    BEGIN
    value: RegisteredValue;
    IF statisticsOn THEN ERROR IllegalUseOfLog;
    value ← ShortTermHeap.Node[
      SIZE[RegisteredValueObject] + (caption.length + 1 + 1) / 2];  -- Extra +1 for quote below
    value↑ ← [
      link: NIL, item: item,
      caption: [length: 0, maxlength: caption.length + 1, text:]];
    String.AppendString[@value.caption, caption];
    IF caption[caption.length - 1] ~= ': THEN
      String.AppendChar[@value.caption, ':];
    IF lastValue = NIL THEN firstValue ← value ELSE lastValue.link ← value;
    lastValue ← value;
    nValues ← nValues + 1;
    END;  --DisplayNumber

  -- Typescript Procedures --

  SetTypescriptParameters: PUBLIC ENTRY PROCEDURE [
    tsPages, tsLines: CARDINAL, font: STRING ← NIL] =
    -- This procedure alters the defaults for the typescript region of the display. This procedure, if called at all, must be called before TypescriptOn.
    BEGIN IF typescriptOn THEN ERROR IllegalUseOfLog; END;  --SetTypescriptParameters

  -- Shortcuts for putting things on the screen and into the log file
  
  ShowLine: PUBLIC PROCEDURE [s: STRING] =
    BEGIN
    LogDefs.WriteLine[s];
    LogDefs.WriteLogEntry[s];
    END;
    
  ShowTwoStrings: PUBLIC PROCEDURE [head: STRING, tail: STRING] =
    BEGIN
    s: STRING = [250];
    String.AppendString[s, head];
    String.AppendString[s, tail];
    LogDefs.WriteLine[s];
    LogDefs.WriteLogEntry[s];
    END;
    
  ShowThreeStrings: PUBLIC PROCEDURE [head: STRING, middle: STRING, tail: STRING] =
    BEGIN
    s: STRING = [250];
    String.AppendString[s, head];
    String.AppendString[s, middle];
    String.AppendString[s, tail];
    LogDefs.WriteLine[s];
    LogDefs.WriteLogEntry[s];
    END;
    
  ShowNumber: PUBLIC PROCEDURE [head: STRING, number: LONG CARDINAL, tail: STRING] =
    BEGIN
    s: STRING = [250];
    String.AppendString[s, head];
    String.AppendLongDecimal[s, number];
    String.AppendString[s, tail];
    LogDefs.WriteLine[s];
    LogDefs.WriteLogEntry[s];
    END;
    
 

  -- Internal Procedures --

  Initialize: PROCEDURE =
    -- Initializes all global variables.  No initialization should occur in the variable declarations, since Initialize must restore the complete initial state of the global variables and is called from two places (the main body and DisplayOff).
    BEGIN
    firstValue ← lastValue ← NIL;
    nValues ← 0;
    statisticsOn ← typescriptOn ← FALSE;
    statsRefreshInterval ← defaultRefreshInterval;
    tty ← TTY.Create["GVServer.log"L];
    END;  --Initialize

  -- Main Body --

  START LogDisplayHot;
  Initialize[];
  END.

Created by Levin on February 7, 1980  8:16 AM.
Changed by Redell on 20-May-81 19:38:33, Pilot version.
Changed by Randy on 30-Jul-81 17:09:22, Give TTY.Create a non-null string.