<<>> <> <> <> <> <> <<>> DIRECTORY Commander, CommandTool, Feedback, FeedbackClasses, FileNames, FS, FSExtras, GGFileOps, GGModelTypes, GGParseIn, GGScene, GGSlice, GGSliceOps, GGUtility, Imager, ImagerInterpress, IO, Process, Real, Rope; GGToIPImpl: CEDAR PROGRAM IMPORTS Commander, CommandTool, Feedback, FeedbackClasses, FileNames, FS, FSExtras, GGFileOps, GGParseIn, GGScene, GGSlice, GGSliceOps, GGUtility, Imager, ImagerInterpress, IO, Process, Real, Rope = BEGIN IPFromGG: PROC[ggName, ipName: Rope.ROPE, router: Feedback.MsgRouter, camera: GGModelTypes.Camera] = { DrawObjects: PROC [dc: Imager.Context, scene: GGModelTypes.Scene, camera: GGModelTypes.Camera] = { DoDrawObject: PROC [slice: GGModelTypes.Slice] RETURNS [done: BOOL _ FALSE] = { GGSliceOps.DrawParts[slice, NIL, dc, camera, FALSE]; }; Imager.SetColor[dc, Imager.black]; [] _ GGScene.WalkSlices[scene, first, DoDrawObject]; }; DoIP: PROC [dc: Imager.Context] = { metersPerPixel: REAL = 0.0254/72.0; Imager.ScaleT[dc, metersPerPixel]; DrawObjects[dc, scene, camera]; }; scene: GGModelTypes.Scene; f: IO.STREAM; ipRef: ImagerInterpress.Ref; ggFullName, ipFullName: Rope.ROPE; success: BOOL _ FALSE; BEGIN IF Rope.Equal[ipName, NIL] THEN { Feedback.Append[router, oneLiner, $Complaint, "GGToIP failed: NIL IP filename"]; RETURN; }; [ipFullName, success] _ GGFileOps.GetInterpressFileName["GGToIP", ipName, FSExtras.GetWDir[], router]; IF NOT success THEN { Feedback.PutF[router, oneLiner, $Complaint, "GGToIP failed: %g", [rope[ipName]] ]; RETURN; }; IF Rope.Equal[ggName, NIL] THEN { Feedback.Append[router, oneLiner, $Complaint, "GGToIP failed: NIL Gargoyle filename"]; RETURN; }; [ggFullName, success] _ GGFileOps.GetGargoyleFileName["GGToIP", ggName, FSExtras.GetWDir[], router]; IF NOT success THEN { Feedback.PutF[router, oneLiner, $Complaint, "GGToIP failed: %g", [rope[ggName]] ]; RETURN; }; f _ FS.StreamOpen[ggFullName, $read ! FS.Error, IO.Error => GOTO Abort;]; scene _ GGScene.CreateScene[]; [success, ] _ FileinSceneOnly[f, scene, router, camera]; IF NOT success THEN GOTO Fail; ipRef _ ImagerInterpress.Create[ipFullName]; Feedback.PutF[router, begin, $Feedback, "Creating IP file %g . . . ", [rope[ipFullName]] ]; ImagerInterpress.DoPage[ipRef, DoIP, 1.0]; ImagerInterpress.Close[ipRef]; IO.Close[f]; Feedback.PutF[router, end, $Feedback, "Done"]; EXITS Abort => Feedback.PutF[router, oneLiner, $Complaint, "GGToIP failed: could not find %g (FS or IO Error)", [rope[ggFullName]] ]; Fail => Feedback.PutF[router, oneLiner, $Complaint, "GGToIP failed: malformed scene in %g", [rope[ggFullName]] ]; END; }; IPFromGGCommand: Commander.CommandProc = { TryPattern: PROC [dest, source: Rope.ROPE _ NIL, isArrow: BOOL _ FALSE] = { ENABLE FS.Error => IF error.group # $bug THEN { IO.PutRope[out, " -- "]; IO.PutRope[out, error.explanation]; GO TO err}; EachFile: FS.NameProc = { <<[fullFName: ROPE] RETURNS [continue: BOOL]>> ipName: Rope.ROPE = IF dest#NIL THEN dest ELSE Rope.Concat[GGFileOps.FilenameMinusExtension[fullFName], ".ip"]; continue _ FALSE; Process.CheckForAbort[]; IPFromGG[fullFName, ipName, router, camera]; sawSomeFile _ continue _ TRUE; }; IF isArrow AND source#NIL THEN { -- new style syntax: GGToIP newfile.ip _ oldfile.gargoyle dest _ FileNames.ResolveRelativePath[dest]; dest _ FS.ExpandName[dest].fullFName; } ELSE { -- old style syntax: GGToIP oldfile.gargoyle source _ dest; -- never really was a destination dest _ NIL; -- needed above }; source _ FileNames.ResolveRelativePath[source]; source _ FS.ExpandName[source].fullFName; <> <> FS.EnumerateForNames[source, EachFile]; EXITS err => {IO.PutRope[out, "\n"]; RETURN}; }; dest, arrow, source: Rope.ROPE; sawSomeFile: BOOL _ FALSE; camera: GGModelTypes.Camera _ NEW[GGModelTypes.CameraObj _ [quality, print, FALSE, FALSE, 1.0]]; out: IO.STREAM _ cmd.out; argv: CommandTool.ArgumentVector _ CommandTool.Parse[cmd: cmd ! CommandTool.Failed => {msg _ errorMsg; GO TO failed}]; router: Feedback.MsgRouter _ Feedback.CreateRouter[]; msgHandler: Feedback.MsgHandler _ FeedbackClasses.CreateHandlerOnStream[cmd.out, TRUE, NIL]; Feedback.SetMultiHandler[router, LIST[$Feedback, $Complaint], msgHandler]; FOR i: NAT IN [1..argv.argc) DO dest _ argv[i]; arrow _ IF i {result _ $Failure}; }; <> Camera: TYPE = GGModelTypes.Camera; Scene: TYPE = GGModelTypes.Scene; Slice: TYPE = GGModelTypes.Slice; SliceClass: TYPE = GGModelTypes.SliceClass; FileinSceneOnly: PROC [f: IO.STREAM, scene: Scene, router: Feedback.MsgRouter, camera: Camera] RETURNS [success: BOOL _ FALSE, sceneName: Rope.ROPE] = { <> ENABLE GGParseIn.SyntaxError => { Feedback.PutF[router, oneLiner, $Complaint, "position: %g, wasThere: %g, notThere: %g", [integer[position]], [rope[wasThere]], [rope[notThere]] ]; GOTO Abort; }; version: REAL; count: NAT; entity: Slice; finger, newEntities: LIST OF Slice; <> GGParseIn.ReadWRope[f, "Gargoyle file for scene: "]; sceneName _ GGParseIn.ReadLine[f]; GGParseIn.ReadWRope[f, "Produced by version"]; version _ GGParseIn.ReadWReal[f]; version _ Real.Round[version*100.0]/100.0; -- compensate for fuzzy ReadWReal of version <> IF version >= 8607.17 THEN SkipOptions[f]; <> GGParseIn.ReadWRope[f, "Entities:"]; GGParseIn.ReadWRope[f, "["]; count _ GGParseIn.ReadWNAT[f]; GGParseIn.ReadWRope[f, "]:"]; GGParseIn.ReadWhiteSpace[f]; [newEntities, finger] _ GGUtility.StartSliceList[]; FOR i: NAT IN[1..count] DO entity _ FileinEntity[f, version, router, camera]; IF entity#NIL THEN [newEntities, finger] _ GGUtility.AddSlice[entity, newEntities, finger]; ENDLOOP; <> IO.Close[f]; <> GGScene.AddSlices[scene, newEntities]; <> <> <> RETURN[TRUE, sceneName]; EXITS Abort => {}; -- RETURN[FALSE, NIL]; }; 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 IsEndLine[nextChar] THEN { [] _ IO.GetChar[f]; twoCRsFound _ TRUE; }; LOOP}; good _ GGParseIn.ReadHorizontalBlank[f]; IF NOT good THEN { nextChar _ IO.PeekChar[f]; IF IsEndLine[nextChar] THEN { [] _ IO.GetChar[f]; twoCRsFound _ TRUE; }; LOOP}; option _ GGParseIn.ReadLine[f]; <> nextChar _ IO.PeekChar[f]; IF IsEndLine[nextChar] THEN { [] _ IO.GetChar[f]; twoCRsFound _ TRUE; }; ENDLOOP; }; FileinEntity: PROC [f: IO.STREAM, version: REAL, router: Feedback.MsgRouter, camera: Camera] RETURNS [entity: Slice] = { nextWord: Rope.ROPE; IF version > 8605.22 THEN { IF version >= 8705.14 THEN { entity _ GGSliceOps.FileinSlice[f, version, router, camera]; } ELSE { nextWord _ GGParseIn.ReadWWord[f]; SELECT TRUE FROM Rope.Equal[nextWord, "Outline:"] => { class: SliceClass _ GGSlice.FetchSliceClass[$Outline]; entity _ class.filein[f, version, router, camera]; }; Rope.Equal[nextWord, "Slice"] => { entity _ GGSliceOps.FileinSlice[f, version, router, camera]; }; ENDCASE => ERROR } } ELSE { nextWord _ GGParseIn.ReadWWord[f]; SELECT TRUE FROM Rope.Equal[nextWord, "Outline:"] => { class: SliceClass _ GGSlice.FetchSliceClass[$Outline]; entity _ class.filein[f, version, router, camera]; }; Rope.Equal[nextWord, "Cluster"] => { entity _ GGSliceOps.FileinSlice[f, version, router, camera]; }; ENDCASE => ERROR; }; }; IsEndLine: PROC [c: CHAR] RETURNS [BOOL] = { RETURN[c=IO.CR OR c=IO.LF]; }; useage: Rope.ROPE = "useage:\nGGToIP list of Gargoyle filenames\n or\nGGToIP OutputFile.ip _ InputFile.gargoyle\n"; Commander.Register[ key: "GGToIP", proc: IPFromGGCommand, doc: useage]; Commander.Register[ key: "GGToInterpress", proc: IPFromGGCommand, doc: useage]; Commander.Register[ key: "GargoyleToIP", proc: IPFromGGCommand, doc: useage]; Commander.Register[ key: "GargoyleToInterpress", proc: IPFromGGCommand, doc: useage]; Commander.Register[key: "IPFromGG", proc: IPFromGGCommand, doc: "useage:\nIPFromGG list of Gargoyle filenames\n or\nIPFromGG OutputFile.ip _ InputFile.gargoyle\n"]; END.