-- file: Pilot> STPsE.mesa - Simple/Stream Transfer Protocol 
  -- Edited by:
    -- Mark on: Feb 12, 1981 11:21 PM
    -- Smokey on: Feb 6, 1981 4:58 PM
    -- Karlton on: October 10, 1980  2:44 PM
    
DIRECTORY
  Compatibility USING [SHandle],
  Date USING [StringToPacked],
  Inline USING [BITAND],
  PupStream USING [PupByteStreamAbort],
  Segments USING [Access, FileNameProblem, Read, Write],
  STP,
  STPOps,
  Stream USING [
    EndOfStream, GetByte, Handle, InputOptions, Object, SetInputOptions],
  Streams USING [GetIndex, GetTimes, NewStream, SetIndex, SetTimes],
  Storage USING [EmptyString, StringLength],
  Time USING [Current, Packed];
  
STPsE: MONITOR
  IMPORTS
    Inline, PupStream, Segments, Storage, STP, STPOps, Stream,
    Streams, Time, Date
  EXPORTS STP, STPOps =
  BEGIN OPEN STPOps;
  
  Object: PUBLIC TYPE = STPOps.Object;
  
  -- HACK to smash connection closed 
  
  SmashClosed: PUBLIC ENTRY PROCEDURE [stp: STPOps.Handle] =
    BEGIN
    IF stp = NIL OR stp.byteStream = NIL THEN RETURN;
    -- First smash connection so it will not give us any grief, THEN close it
    PupStream.PupByteStreamAbort[stp.byteStream, "Unwinding..."L];
    STP.Close[stp ! STP.Error => IF code = noConnection THEN CONTINUE];
    END;
    
-- For incompatable Alto/Pilot Stream Objects

  FillInStreamObject: PUBLIC PROCEDURE[handle: Stream.Handle] =
    BEGIN OPEN STPOps;
    handle↑ ← Stream.Object[
      options: NULL,
      get: GetBlock, getByte: GetByte, getWord: GetWord,
      put: PutBlock, putByte: PutByte, putWord: PutWord,
      setSST: STP.SetSSTNop, sendAttention: STP.SendAttentionNop,
      waitAttention: STP.WaitAttentionNop, delete: DeleteRemoteStream];
    END;
    
-- FileStream stuff

  CreateFileStream: PUBLIC PROCEDURE [
    file: STRING,
    access: STP.Access ← read,
    stream: Compatibility.SHandle ← NIL,
    fileType: STP.FileType ← unknown,
    options: Stream.InputOptions ← STP.defaultOptions]
    RETURNS [Stream.Handle] =
    BEGIN OPEN Streams;
    acc: Segments.Access = IF access = read THEN Segments.Read ELSE Segments.Write;
    IF stream = NIL THEN 
      BEGIN
      IF Storage.StringLength[file] = 0 THEN
	GenerateErrorString[illegalFileName, NIL];
      stream ← NewStream[file, acc ! Segments.FileNameProblem[] => CONTINUE];
      END;
    IF stream = NIL THEN GenerateErrorString[noSuchFile, NIL];
    Stream.SetInputOptions[stream, options];
    RETURN[stream];
    END;
    
  FindFileType: PUBLIC PROCEDURE [stream: Stream.Handle]
    RETURNS [fileType: STP.FileType] =
    BEGIN
    currentIndex: LONG CARDINAL ← Streams.GetIndex[stream];
    Streams.SetIndex[stream, 0];
    fileType ← text;
    DO ENABLE Stream.EndOfStream => GOTO streamEND;
      IF (Inline.BITAND[Stream.GetByte[stream], 200B]) # 0 THEN
	{fileType ← binary; EXIT};
      REPEAT streamEND => NULL;
      ENDLOOP;
    Streams.SetIndex[stream, currentIndex];
    END;
    
  GetFileTimes: PUBLIC PROCEDURE [stream: Stream.Handle]
    RETURNS [create, write, read: Time.Packed] =
    BEGIN
    [create, write, read] ← Streams.GetTimes[stream];
    END;
    
  SetFileDates: PUBLIC PROCEDURE [stp: STPOps.Handle, stream: Stream.Handle] =
    BEGIN
    cTime: Time.Packed;
    cTime ← IF Storage.EmptyString[stp.plist[createDate]] THEN Time.Current[]
      ELSE Date.StringToPacked[stp.plist[createDate]];
    Streams.SetTimes[h: stream, create: cTime, read: [0], write: [0]]; 
    END;
    
  END. -- of STPsE