<> <> <> <> <> DIRECTORY Atom, Convert, FS, GGBasicTypes, GGError, GGEvent, GGFileIn, GGInterfaceTypes, GGModelTypes, GGObjects, GGOutline, GGParseIn, GGSegmentTypes, GGSlice, GGUtility, Imager, ImagerColor, IO, Rope, ViewerClasses; GGFileInImpl: CEDAR PROGRAM IMPORTS Atom, Convert, GGError, GGEvent, GGObjects, GGOutline, GGParseIn, GGSlice, GGUtility, IO, Rope EXPORTS GGFileIn = BEGIN Viewer: TYPE = ViewerClasses.Viewer; Color: TYPE = Imager.Color; GargoyleData: TYPE = GGInterfaceTypes.GargoyleData; Outline: TYPE = GGModelTypes.Outline; Point: TYPE = GGBasicTypes.Point; Scene: TYPE = GGModelTypes.Scene; Segment: TYPE = GGSegmentTypes.Segment; SegmentClass: TYPE = GGSegmentTypes.SegmentClass; Slice: TYPE = GGModelTypes.Slice; SliceClass: TYPE = GGModelTypes.SliceClass; StrokeEnd: TYPE = Imager.StrokeEnd; Traj: TYPE = GGModelTypes.Traj; Problem: PUBLIC SIGNAL [msg: Rope.ROPE] = GGError.Problem; FileinSceneAndOptions: PUBLIC PROC [f: IO.STREAM, gargoyleData: GargoyleData] = { sceneName: Rope.ROPE; scene: Scene _ gargoyleData.scene; version: REAL; count: NAT; entity: REF ANY; finger, newEntities: LIST OF REF ANY; <> GGParseIn.ReadBlankAndRope[f, "Gargoyle file for scene:"]; sceneName _ GGParseIn.ReadBlankAndWord[f]; GGParseIn.ReadBlankAndRope[f, "Produced by version"]; version _ GGParseIn.ReadBlankAndReal[f]; <> IF version >= 8607.17 THEN ReadOptions[f, version, gargoyleData]; <> GGParseIn.ReadBlankAndRope[f, "Entities:"]; GGParseIn.ReadBlankAndRope[f, "["]; count _ GGParseIn.ReadBlankAndNAT[f]; GGParseIn.ReadBlankAndRope[f, "]:"]; GGParseIn.ReadWhiteSpace[f]; [newEntities, finger] _ GGUtility.StartList[]; FOR i: NAT IN[1..count] DO entity _ FileinEntity[f, version, gargoyleData.feedback]; IF entity#NIL THEN [newEntities, finger] _ GGUtility.AddEntity[entity, newEntities, finger]; ENDLOOP; GGObjects.AddEntities[scene, newEntities]; f.Close[]; }; ReadOptions: PROC [f: IO.STREAM, version: REAL, gargoyleData: GargoyleData] = { keyWord, option: Rope.ROPE; good: BOOL; nextChar: CHAR; twoCRsFound: BOOL _ FALSE; <> UNTIL twoCRsFound DO [keyWord, good] _ GGParseIn.ReadKeyWord[f]; IF NOT good THEN { nextChar _ IO.PeekChar[f]; IF nextChar = IO.CR THEN { [] _ IO.GetChar[f]; twoCRsFound _ TRUE; }; LOOP}; good _ GGParseIn.ReadHorizontalBlank[f]; IF NOT good THEN { nextChar _ IO.PeekChar[f]; IF nextChar = IO.CR THEN { [] _ IO.GetChar[f]; twoCRsFound _ TRUE; }; LOOP}; option _ GGParseIn.ReadLine[f]; ProcessOption[keyWord, option, version, gargoyleData]; nextChar _ IO.PeekChar[f]; IF nextChar = IO.CR THEN { [] _ IO.GetChar[f]; twoCRsFound _ TRUE; }; ENDLOOP; }; ProcessOption: PROC[keyWord, option: Rope.ROPE, version: REAL, gargoyleData: GargoyleData] = { optionStream: IO.STREAM _ IO.RIS[option]; optionList: LIST OF Rope.ROPE; value: REAL; SELECT TRUE FROM Rope.Equal[keyWord, "Slope", FALSE] => { optionList _ GGParseIn.ReadListOfRope[optionStream]; FOR list: LIST OF Rope.ROPE _ optionList, list.rest UNTIL list = NIL DO value _ Convert.RealFromRope[list.first]; GGEvent.AddSlopeInternal[gargoyleData, value]; ENDLOOP; }; Rope.Equal[keyWord, "Angle", FALSE] => { optionList _ GGParseIn.ReadListOfRope[optionStream]; FOR list: LIST OF Rope.ROPE _ optionList, list.rest UNTIL list = NIL DO value _ Convert.RealFromRope[list.first]; GGEvent.AddAngleInternal[gargoyleData, value]; ENDLOOP; }; Rope.Equal[keyWord, "Radius", FALSE] => { optionList _ GGParseIn.ReadListOfRope[optionStream]; FOR list: LIST OF Rope.ROPE _ optionList, list.rest UNTIL list = NIL DO value _ Convert.RealFromRope[list.first]; GGEvent.AddRadiusInternal[gargoyleData, value]; ENDLOOP; }; Rope.Equal[keyWord, "LineDistance", FALSE] => { optionList _ GGParseIn.ReadListOfRope[optionStream]; FOR list: LIST OF Rope.ROPE _ optionList, list.rest UNTIL list = NIL DO value _ Convert.RealFromRope[list.first]; GGEvent.AddDistanceInternal[gargoyleData, value]; ENDLOOP; }; Rope.Equal[keyWord, "Midpoints", FALSE] => { on, good: BOOL; [on, good] _ GGParseIn.ReadBOOL[optionStream, version]; GGEvent.SetMidpointsInternal[gargoyleData, on AND good]; }; ENDCASE => SIGNAL Problem[msg: "Unknown keyword in gargoyle file."]; }; -- end ProcessOption FileinSceneOnly: PUBLIC PROC [f: IO.STREAM, scene: Scene] = { sceneName: Rope.ROPE; version: REAL; count: NAT; entity: REF ANY; finger, newEntities: LIST OF REF ANY; <> GGParseIn.ReadBlankAndRope[f, "Gargoyle file for scene:"]; sceneName _ GGParseIn.ReadBlankAndWord[f]; GGParseIn.ReadBlankAndRope[f, "Produced by version"]; version _ GGParseIn.ReadBlankAndReal[f]; <> IF version >= 8607.17 THEN SkipOptions[f]; <> GGParseIn.ReadBlankAndRope[f, "Entities:"]; GGParseIn.ReadBlankAndRope[f, "["]; count _ GGParseIn.ReadBlankAndNAT[f]; GGParseIn.ReadBlankAndRope[f, "]:"]; [newEntities, finger] _ GGUtility.StartList[]; FOR i: NAT IN[1..count] DO entity _ FileinEntity[f, version, NIL]; IF entity#NIL THEN [newEntities, finger] _ GGUtility.AddEntity[entity, newEntities, finger]; ENDLOOP; GGObjects.AddEntities[scene, newEntities]; f.Close[]; }; SkipOptions: PROC [f: IO.STREAM] = { keyWord, option: Rope.ROPE; good: BOOL; nextChar: CHAR; twoCRsFound: BOOL _ FALSE; UNTIL twoCRsFound DO [keyWord, good] _ GGParseIn.ReadKeyWord[f]; IF NOT good THEN { nextChar _ IO.PeekChar[f]; IF nextChar = IO.CR THEN { [] _ IO.GetChar[f]; twoCRsFound _ TRUE; }; LOOP}; good _ GGParseIn.ReadHorizontalBlank[f]; IF NOT good THEN { nextChar _ IO.PeekChar[f]; IF nextChar = IO.CR THEN { [] _ IO.GetChar[f]; twoCRsFound _ TRUE; }; LOOP}; option _ GGParseIn.ReadLine[f]; <> nextChar _ IO.PeekChar[f]; IF nextChar = IO.CR THEN { [] _ IO.GetChar[f]; twoCRsFound _ TRUE; }; ENDLOOP; }; FileinEntity: PROC [f: IO.STREAM, version: REAL, feedback: Viewer] RETURNS [entity: REF ANY] = { nextWord: Rope.ROPE; nextWord _ GGParseIn.ReadBlankAndWord[f]; IF version > 8605.22 THEN SELECT TRUE FROM Rope.Equal[nextWord, "Outline:"] => { class: GGModelTypes.OutlineClass _ GGOutline.FetchSliceClass[$Outline]; entity _ class.filein[f, version, feedback]; }; Rope.Equal[nextWord, "Slice"] => { entity _ FileinSlice[f, version, feedback]; }; ENDCASE => ERROR ELSE SELECT TRUE FROM Rope.Equal[nextWord, "Outline:"] => { class: GGModelTypes.OutlineClass _ GGOutline.FetchSliceClass[$Outline]; entity _ class.filein[f, version, feedback]; }; Rope.Equal[nextWord, "Cluster"] => { entity _ FileinSlice[f, version, feedback]; }; ENDCASE => ERROR; }; FileinSlice: PROC [f: IO.STREAM, version: REAL, feedback: Viewer] RETURNS [slice: Slice] = { className: Rope.ROPE; type: ATOM; childCount: NAT; class: SliceClass; GGParseIn.ReadBlankAndRope[f, "(class:"]; className _ GGParseIn.ReadBlankAndWord[f]; GGParseIn.ReadBlankAndRope[f, ")"]; GGParseIn.ReadBlankAndRope[f, "["]; childCount _ GGParseIn.ReadBlankAndNAT[f]; GGParseIn.ReadBlankAndRope[f, "]:"]; GGParseIn.ReadBlankAndRope[f, "Data:"]; type _ SliceClassFromRope[className]; class _ GGSlice.FetchSliceClass[type]; slice _ class.filein[f, version, feedback]; }; SliceClassFromRope: PROC [className: Rope.ROPE] RETURNS [type: ATOM] = { RETURN[Atom.MakeAtom[className] ]; }; END.