DIRECTORY Atom, Commander, CommanderOps, Convert, FS, Imager, ImagerBox, ImagerError, ImagerMaskCapture, ImagerTransformation, InterpressInterpreter, IPtoPS, IO, IPMaster, Process, Rope, SF; IPtoPSCmdImpl: CEDAR PROGRAM IMPORTS Atom, Commander, CommanderOps, Convert, FS, Imager, ImagerBox, ImagerError, ImagerMaskCapture, ImagerTransformation, InterpressInterpreter, IPtoPS, IO, IPMaster, Process, Rope ~ BEGIN ROPE: TYPE ~ Rope.ROPE; Master: TYPE ~ InterpressInterpreter.Master; LogError: PROC [out: IO.STREAM, class: INT, code: ATOM, explanation: ROPE] ~ { IO.PutRope[out, SELECT class FROM InterpressInterpreter.classMasterError => "Master Error: ", InterpressInterpreter.classMasterWarning => "Master Warning: ", InterpressInterpreter.classAppearanceError => "Appearance Error: ", InterpressInterpreter.classAppearanceWarning => "Appearance Warning: ", InterpressInterpreter.classComment => "Comment: ", ENDCASE => Rope.Cat["Class ", Convert.RopeFromInt[class], " Error: "] ]; IO.PutRope[out, explanation]; IO.PutRope[out, " . . . "]; }; GetCmdToken: PROC [stream: IO.STREAM] RETURNS [rope: ROPE ¬ NIL] ~ { CmdTokenBreak: PROC [char: CHAR] RETURNS [IO.CharClass] ~ { IF char = '_ OR char = '[ OR char = '] THEN RETURN[break]; IF char = ' OR char = '\t OR char = ', OR char = '; OR char = '\n THEN RETURN[sepr]; RETURN[other]; }; rope ¬ IO.GetTokenRope[stream, CmdTokenBreak ! IO.EndOfStream => CONTINUE].token; }; GetToken: PROC [stream: IO.STREAM] RETURNS [rope: ROPE ¬ NIL] ~ { TokenBreak: PROC [char: CHAR] RETURNS [IO.CharClass] ~ { IF char = '_ THEN RETURN[break]; IF char = ' OR char = '\t OR char = ', OR char = '; OR char = '\n THEN RETURN[sepr]; RETURN[other]; }; rope ¬ IO.GetTokenRope[stream, TokenBreak ! IO.EndOfStream => CONTINUE].token; }; Encapsulate: PROC [ip: Master] RETURNS [ROPE] ~ { Op: PROC [context: Imager.Context] ~ { Imager.SetColor[context, Imager.black]; Imager.SetStrokeEnd[context, square]; Imager.SetStrokeWidth[context, 0.0]; Imager.SetAmplifySpace[context, 1.0]; InterpressInterpreter.DoPage[ip, 1, context, NIL]; }; m: Imager.Transformation ¬ ImagerTransformation.Scale[150.0/0.0254]; -- ~150 pixels/inch n: Imager.Transformation ¬ ImagerTransformation.PostScale[m, 0.0254]; -- back to inches b: SF.Box ¬ ImagerMaskCapture.CaptureBounds[Op, m ! ImagerMaskCapture.Cant =>RESUME]; r: ImagerBox.Rectangle ¬ ImagerTransformation.InverseTransformRectangle[ n, ImagerBox.RectangleFromBox[[b.min.s, b.min.f, b.max.s, b.max.f]]]; RETURN[IO.PutFLR["%%BoundingBox: %g %g %g %g", LIST[IO.real[72.0*r.x], IO.real[72.0*r.y], IO.real[72.0*(r.x+r.w)], IO.real[72.0*(r.y+r.h)]]] ]; }; Command: Commander.CommandProc ~ { ENABLE IPMaster.Error => {msg ¬ error.explanation; GOTO Bad}; Log: InterpressInterpreter.LogProc ~ { LogError[cmd.out, class, ImagerError.AtomFromErrorCode[code], explanation]; }; Translate: PROC RETURNS [warns: ROPE ¬ NIL] ~ { ENABLE IPtoPS.Warn => {warns ¬ Rope.Cat[warns, "\n\t", reason]; RESUME}; nBad: INTEGER ¬ 0; user: ROPE ¬ NARROW[CommanderOps.GetProp[NIL, $USER]]; debugStream: IO.STREAM ¬ IF debug THEN cmd.out ELSE NIL; comment: ROPE ¬ IF encapsulate THEN Encapsulate[ip] ELSE NIL; c: Imager.Context ~ IPtoPS.Create[out, ip.pages, user, comment, compact, debugStream]; FOR i: INT IN [1..ip.pages] DO Page: PROC ~ { Imager.ScaleT[c, 72.0/0.0254]; InterpressInterpreter.DoPage[master: ip, page: i, context: c, log: Log]; }; Process.CheckForAbort[]; IO.PutF1[cmd.out, "[%g", IO.int[i]]; IO.PutF1[out, "%%%%page %g\n", IO.int[i]]; Imager.DoSave[c, Page]; IO.PutF1[out, "%% end page %g\n", IO.int[i]]; IO.PutRope[out, "showpage\n"]; IO.PutRope[cmd.out, "] "]; ENDLOOP; IO.PutF1[out, "\n%%%%Trailer\n%%%%Pages: %g\n", IO.int[ip.pages]]; warns ¬ Rope.Concat[warns, SELECT (nBad ¬ IPtoPS.NInvalidChars[c]) FROM 1 => "\n\t1 invalid char (replaced with a space)", > 1 => IO.PutFR1["\n\t%g invalid chars (replaced with spaces)", IO.int[nBad]], ENDCASE => NIL]; IPtoPS.Close[c]; }; ip: Master; out: IO.STREAM; warnings, input, output: ROPE ¬ NIL; compact, debug, encapsulate: BOOL ¬ FALSE; argv: CommanderOps.ArgumentVector ¬ CommanderOps.Parse[cmd]; Atom.PutProp[$IPtoPSDebug, $Out, cmd.out]; FOR i: INTEGER IN [1..argv.argc) DO SELECT TRUE FROM Rope.Equal[argv[i], "-compact"] => compact ¬ TRUE; Rope.Equal[argv[i], "-debug"] => debug ¬ TRUE; Rope.Equal[argv[i], "-encapsulate"] => encapsulate ¬ TRUE; Rope.Equal[argv[i], "_"] => IF i IN (1..argv.argc-1) THEN { output ¬ argv[i-1]; input ¬ argv[i+1]; } ELSE RETURN[$Failure, doc]; ENDCASE => input ¬ argv[i] ENDLOOP; IF Rope.IsEmpty[input] THEN RETURN[$Failure, doc]; input ¬ FS.FileInfo[input ! FS.Error => {msg ¬ error.explanation; GOTO Bad}].fullFName; IF Rope.IsEmpty[output] THEN { cp: FS.ComponentPositions; [input, cp] ¬ FS.ExpandName[input]; output ¬ Rope.Cat[Rope.Substr[input, cp.base.start, cp.base.length], ".", "ps"]; }; ip ¬ InterpressInterpreter.Open[input, Log]; IF encapsulate AND ip.pages > 1 THEN RETURN[ $Failure, IO.PutFR1["%g pages (encapsulated PS must be one page)", IO.int[ip.pages]]]; out ¬ FS.StreamOpen[output, create]; IO.PutF1[cmd.out, "Reading %g . . . ", IO.rope[input]]; warnings ¬ Translate[ ! IPMaster.Error => {msg ¬ error.explanation; GOTO Bad}; FS.Error => {msg ¬ error.explanation; GOTO Bad} ]; output ¬ FS.FileInfo[output ! FS.Error => {output ¬ "Output file(s)"; CONTINUE}].fullFName; IF warnings # NIL THEN IO.PutF1[cmd.out, "\nWarnings:%g\n", IO.rope[warnings]]; IO.PutF1[cmd.out, "%g written.\n", IO.rope[output]]; EXITS Bad => RETURN[$Failure, IF Rope.IsEmpty[msg] THEN doc ELSE Rope.Concat["\n", msg]]; }; doc: ROPE ~ " convert Interpress file to PostScript file; usage: IPtoPS (InterpressToPostscript) [ _ ] [-