-- File: SVFilesImpl.mesa
-- Last edited by Bier on December 18, 1982 1:37 am
-- Author: Eric Bier on March 22, 1983 11:16 am
-- Contents: Interfaces which make creating scenes look like opening files.

DIRECTORY
 DisplayList3d,
 FileIO,
 Filein3d,
 Fileout3d,
IO,
 MessageWindow,
 Rope,
 SVArtwork,
 SVFiles,
 TFI3d;

SVFilesImpl: PROGRAM
IMPORTS DisplayList3d, FileIO, Filein3d, Fileout3d, IO, MessageWindow, Rope, SVArtwork, TFI3d
EXPORTS SVFiles =

BEGIN

Scene: TYPE = DisplayList3d.Scene;
SceneTable: TYPE = LIST OF Scene;

FindScene: PRIVATE PROC [name: Rope.ROPE, table: SceneTable] RETURNS [scene: Scene, success: BOOL] = {
 success ← FALSE;
FOR list: SceneTable ← table, list.rest UNTIL list = NIL OR success DO
  IF Rope.Equal[s1: name, s2: list.first.name, case: TRUE] THEN {
   success ← TRUE;
   scene ← list.first;
   }; 
ENDLOOP;
 };

AddSceneToTable: PRIVATE PROC [scene: Scene, table: SceneTable] RETURNS [newtable: SceneTable] = {
 newtable ← CONS[scene, table];
 };

OpenScene: PUBLIC PROC [picName: Rope.ROPE] RETURNS [scene: Scene, success: BOOL] = {
-- Look for the pic file on the local disk. If there, read in the scene. If not, MessageWindow "file not found" and return success = false.
 f: IO.STREAM;
 [f, success] ← OpenFile[picName];
IF NOT success THEN RETURN; -- OpenFile prints any error messages.
-- now we must turn the text file into a scene.
 [scene, success] ← MakeScene[f, picName]; -- MakeScene will print any error messages
 };


OpenFile: PUBLIC PROC [picName: Rope.ROPE] RETURNS [f: IO.STREAM, success: BOOL] = {
 success ← TRUE;

-- Two possiblilities
-- 1) File doesn't exist. Print error message.
-- 2) File does exist. File it in. Succeed.

 f ← FileIO.Open[picName, read, oldOnly
  !FileIO.OpenFailed => CHECKED {IF why = fileNotFound OR why = illegalFileName THEN {success ← FALSE; CONTINUE}
      ELSE ERROR}];
IF NOT success THEN {
  MessageWindow.Append["Picture file: ", TRUE];
  MessageWindow.Append[picName];
  MessageWindow.Append[" not found."];
  RETURN};
 }; -- end of OpenFile

MakeScene: PRIVATE PROC [f: IO.STREAM, picName: Rope.ROPE] RETURNS [scene: Scene, success: BOOL] = {
 errorPos: NAT;
 errorStream: IO.STREAM;
 errorRope, expected, actual: Rope.ROPE;
 fileNotFound: BOOLFALSE;
 allMapsFound: BOOLTRUE;
 success ← TRUE;
 scene ← DisplayList3d.CreateEmptyScene[picName];
 MessageWindow.Append["Reading scene: ",TRUE];
 MessageWindow.Append[scene.name];
 MessageWindow.Append[" from file: "];
 MessageWindow.Append[picName];
 MessageWindow.Append["..."];
 Filein3d.FileinScene [scene, f
  !TFI3d.RopeNotOnTop => {success ← FALSE; errorPos ← position; expected ← notThere;
   actual ← wasThere; CONTINUE};
   SVArtwork.FileNotFound => {allMapsFound ← FALSE; CONTINUE}];
IF NOT allMapsFound THEN {
  errorStream ← IO.CreateOutputStreamToRope[];
  errorStream.PutF["Some AIS mapping file not found"];
  errorRope ← IO.GetOutputStreamRope[errorStream];
  MessageWindow.Append[errorRope, TRUE];
  success ← FALSE;
  RETURN
  };
IF NOT success THEN {
  errorStream ← IO.CreateOutputStreamToRope[];
  errorStream.PutF["At %g in %g expected '%g' not '%g'",
   [integer[errorPos]], [rope[picName]], [rope[expected]], [rope[actual]]];
  errorRope ← IO.GetOutputStreamRope[errorStream];
  MessageWindow.Append[errorRope, TRUE];
  RETURN
  }
ELSE MessageWindow.Append["Done"];
 }; -- end of MakeScene

SaveScene: PUBLIC PROC [updatedScene: Scene, picName: Rope.ROPE] RETURNS [success: BOOL] = {
-- Check local disk to see that we have a scene with this name. If so, save it as a file on the local disk after confirmation. scene.dirty ← FALSE.
-- If not, MessageWindow "File not found. Use Store." and return success = FALSE.
 f: IO.STREAM;
 success ← TRUE;
 f ← FileIO.Open[picName, overwrite, oldOnly
  !FileIO.OpenFailed => CHECKED {IF why = fileNotFound OR why = illegalFileName THEN
          {success ← FALSE; CONTINUE}
           ELSE ERROR}];
IF success THEN SaveFile[updatedScene, f, picName]
ELSE {MessageWindow.Append["file has no name. Try Store.", TRUE];
   MessageWindow.Blink[]};
 };

SaveFile: PRIVATE PROC [scene: Scene, f: IO.STREAM, picName: Rope.ROPE] = {
 MessageWindow.Append["Writing scene: ",TRUE];
 MessageWindow.Append[scene.name];
 MessageWindow.Append[" to file: "];
 MessageWindow.Append[picName];
 MessageWindow.Append["..."];
 Fileout3d.FileoutScene [scene, f, picName];
 scene.dirty ← FALSE;
 MessageWindow.Append["Done"];
 }; -- end of SaveFile

StoreScene: PUBLIC PROC [unNamedScene: Scene, newPicName: Rope.ROPE] RETURNS [success: BOOL] = {
-- Check the local disk for this name. Ask for confirmation to store to new (or old) file. Store if confirmed.
 f: IO.STREAM;
 fileAlreadyExists: BOOLFALSE;
 confirmation: BOOLFALSE;
 success ← FALSE;

 f ← FileIO.Open[newPicName, write, newOnly
  !FileIO.OpenFailed => CHECKED {IF why = fileAlreadyExists OR why = illegalFileName THEN
        {fileAlreadyExists ← TRUE; CONTINUE}
        ELSE ERROR}];
IF fileAlreadyExists THEN {
  confirmation ← MessageWindow.Confirm["Confirm overwrite of existing pic file"];
  IF confirmation THEN
   f ← FileIO.Open[newPicName, overwrite, oldOnly]
  ELSE RETURN;
  };
 MessageWindow.Append["Writing scene: ",TRUE];
 MessageWindow.Append[newPicName];
 MessageWindow.Append[" to file: "];
 MessageWindow.Append[newPicName];
 MessageWindow.Append["..."];
 Fileout3d.FileoutScene [unNamedScene, f, newPicName];
 MessageWindow.Append["Done"];
 success ← TRUE;
 unNamedScene.dirty ← FALSE;
 unNamedScene.name ← newPicName;
 }; -- end of Save


FileExists: PUBLIC PROC [fileName: Rope.ROPE] RETURNS [answer: BOOLTRUE] = {
s: IO.STREAM ← FileIO.Open[fileName: fileName, createOptions: oldOnly
! FileIO.OpenFailed => TRUSTED {
answer←FALSE;
GOTO notThere;
}];
IO.Close[s];
EXITS
notThere => NULL;
};

FilenameMinusExtension: PUBLIC PROC [wholeName: Rope.ROPE] RETURNS [firstPart: Rope.ROPE] = {
 wholeStream: IO.STREAMIO.RIS[wholeName];
 firstPart ← IO.GetToken[wholeStream, PeriodBreakProc];
 };

PeriodBreakProc: SAFE PROC [char: CHAR] RETURNS [IO.CharClass] = TRUSTED {
SELECT char FROM
 '. => RETURN[sepr];
ENDCASE => RETURN[other];
 };



END.