-- ClassIncreek.mesa
-- Last Edited by Stone, August 31, 1982 1:42 pm
-- Last Edited by McGregor, 1-Sep-81
-- Last Edited by Swinehart, April 14, 1982 10:06 am

DIRECTORY
  ClassInscript USING [Inscript, InscriptPageDescriptor, InscriptPageDescBody, WaitMode],
  Intime USING [DeltaTime, DeltaDeltaTime, EventTime, MsTicks],
  Interminal USING [KeyName, KeyState, MousePosition, PenPosition];

ClassIncreek: DEFINITIONS =
  BEGIN OPEN ClassInscript, T:Intime, K:Interminal;

  NewStdIncreek: PROCEDURE [template: Increek ← NIL] RETURNS [Increek];

Increek: TYPE = REF IncreekObject;

  -- Client Interface for Increeks

Release: PROCEDURE [self: Increek] RETURNS [nilIncreek: Increek];

CopyIncreek: PROCEDURE [self: Increek, template: Increek];
  -- Will not affect mouse grain settings, even if it should.

  -- GetAction can raise IncreekError[outOfBounds],
  --  meaning that prior to or during invocation of the operation,
  --  information has been lost from the inscript.  A Set... operation
  --  that originally succeeds can later result in this ERROR, due to the
  --  effects of additional keyboard input.

GetAction: PROCEDURE [self: Increek, waitMode: WaitMode ← forever, waitInterval: T.MsTicks ← 100,
    acceptance: Acceptance ← clicks] RETURNS [a: ActionBody];

SetAtEarliest: PROCEDURE [self: Increek];

SetAtLatest: PROCEDURE [self: Increek];

SetAtTime: PROCEDURE [self: Increek, eventTime: T.EventTime]
    RETURNS [pR: PosResult];

-- Defaulting arguments selects default settings. 
-- The mouse grain is a hint to the recording entity (e.g., Interminal) that
-- the application using self does not need mouse actions sampled more frequently
-- than every ticks ms., or when motion is less than dots screen points.
-- The mouse position will however always be accurate following a keyboard
-- or mouse button action.   
SetMouseGrain: PROCEDURE [self: Increek, ticks: T.MsTicks←0, dots: INTEGER←0];

GetTime: PROCEDURE [self: Increek] RETURNS [eT: T.EventTime];

GetCurrentTime: PROCEDURE [self: Increek] RETURNS [eT: T.EventTime];

GetPositionFrom: PROCEDURE [self: Increek] RETURNS [p: ViewPosition] = INLINE
    -- This is because Level 1 interfaces can benefit from the state fields of a position.
    -- They don't have to know that a position is the OpaqueIncreekData.
    {RETURN[self]};
    
  IncreekError: -- abstraction -- ERROR[code: IncreekErrorCode];
  IncreekErrorCode: TYPE = {
    outOfBounds -- position no longer valid during ReadAction
    };

InsertAction: PROCEDURE[self: Increek, action: ActionBody];
--inserts an action into the creek.  Useful for simulation, error recovery, etc.

  -- Increek interface implementation --
  IncreekObject: PRIVATE TYPE = InscriptPositionBody; -- NOT fully opaque!

  -- types and constants --

  PosResult: TYPE = {tooEarly, tooLate, onTime};
  WaitMode: TYPE = ClassInscript.WaitMode; -- {forever, dontWait, timed};

  ActionKind: TYPE = MACHINE DEPENDENT {
    deltaEventTime (0), eventTime (1), deltaMouse (2), mousePosition (3), keyDown (4),
    keyUp (5), keyStillDown (6), timedOut (7) -- never stored -- , penPosition(8)};
    -- keyStillDown[value: allUp] is a request to clear state to "all up".
  Acceptance: TYPE = {clicks, clicksAndMotion, all};
  
  DeltaMouse: TYPE = RECORD [ deltaX: [-8..8), deltaY: [-8..8) ];

  Action: TYPE = LONG POINTER TO ActionBody;
  ActionBody: TYPE =  RECORD [
    deltaDeltaTime: T.DeltaDeltaTime ← 0,
    contents:
      SELECT kind: ActionKind FROM
	deltaEventTime => [value: T.DeltaTime ← NULL],
	keyDown, keyStillDown, keyUp => [value: K.KeyName ← NULL],
	eventTime => [eventTime: T.EventTime ← NULL],
	deltaMouse => [value: DeltaMouse ← NULL ],
	mousePosition => [mousePosition: K.MousePosition ← NULL],
	penPosition => [penPosition: K.PenPosition ← NULL],
	timedOut=>NULL, -- no value for timedOut actions
	ENDCASE];

  InscriptPosition: TYPE = REF InscriptPositionBody;
  ViewPosition: TYPE = REF -- READONLY doesn't work! --
    InscriptPositionBody;
  InscriptPositionBody: TYPE = RECORD [
    -- Private to implementation; location in inscript file --
    inscript: PRIVATE ClassInscript.Inscript, -- for releasing
    inscriptPage: PRIVATE ClassInscript.InscriptPageDescriptor,
    	ip1: PRIVATE REF ClassInscript.InscriptPageDescBody,
    iP: PRIVATE ClassInscript.InscriptPageDescriptor, -- specific to current impl. --
    	ip2: PRIVATE REF ClassInscript.InscriptPageDescBody,
    eT: PRIVATE T.EventTime←NULL, -- client shouldn't use

    -- Client-public information; absolute state at that point --
    eventTime: T.EventTime ← NULL,
    mousePosition: K.MousePosition ← NULL,
    keyState: K.KeyState ← NULL,
    chordState: K.KeyState ← NULL,
    downCount: INTEGER ← 0,
    mouseGrainTime: T.MsTicks←NULL,
    mouseGrainDots: INTEGER←NULL];

  END.