<<>> <> <> <> <> <> <> <> <> <> <> <> <> DIRECTORY Commander, Convert, FileNames, FS, Imager, ImagerError, ImagerFontFilter, ImagerInterpress, ImagerPress, InterpressInterpreter, IO, PressConverters, Process, Rope, ShowPress; PressConvertersCommand: CEDAR PROGRAM IMPORTS Commander, Convert, FileNames, FS, Imager, ImagerError, ImagerFontFilter, ImagerInterpress, ImagerPress, InterpressInterpreter, IO, Process, Rope, ShowPress EXPORTS PressConverters ~ BEGIN ROPE: TYPE ~ Rope.ROPE; <> ActionProc: TYPE ~ PressConverters.ActionProc; ProgressProc: TYPE ~ PressConverters.ProgressProc; inch: REAL = 0.0254; -- inches->meters conversion factor ravenPPI: REAL = 300.0; -- pixels per inch on a Raven printer for compression ravenPPM: REAL = ravenPPI/inch; -- pixels per meters on a Raven printer for compression defaultPageWidth: REAL ¬ 8.5*inch; -- for normal sized paper defaultPageHeight: REAL ¬ 11*inch; -- for normal sized paper defaultAISPixelsPerInch: REAL = 72.0; -- for AIS files aisMargin: REAL ¬ 0.25*inch; -- offset of AIS images on regular-sized paper headerSampled: ROPE ¬ "Interpress/Xerox/3.0 "; -- IP header for sampled images aisCaptionFont: ROPE ¬ "xerox/pressfonts/helvetica-mir"; -- to put caption in AIS files aisCaptionLoc: Imager.VEC ¬ [72, 9]; -- where the caption should be in AIS files xcFontBase: Rope.ROPE ¬ "Xerox/xc1-2-2/"; -- prefix to be used for Xerox product fonts <> PressToInterpress: PUBLIC PROC [inputName: Rope.ROPE, interpress: ImagerInterpress.Ref, beginPage, endPage: ProgressProc, msg: IO.STREAM, useXCFonts: BOOL, verbose: BOOL] RETURNS [failed: BOOL ¬ FALSE] ~ { <> showPress: ShowPress.Handle = ShowPress.Open[FileNames.ResolveRelativePath[inputName]]; FOR i: INT IN [1..showPress.lastPart) DO Paint: PROC [context: Imager.Context] ~ { Process.CheckForAbort[]; failed ¬ beginPage[i, showPress.lastPart-1]; IF failed THEN RETURN; IF useXCFonts THEN context ¬ ImagerFontFilter.FilterFonts[context, xc1Map, msg, verbose]; Imager.SetPriorityImportant[context, TRUE]; ShowPress.DrawPressPage[context: context, show: showPress, pageNumber: i]; Process.CheckForAbort[]; failed ¬ endPage[i, showPress.lastPart-1]; }; ImagerInterpress.DoPage[self: interpress, action: Paint, scale: 1.0E-5]; IF failed THEN EXIT; ENDLOOP; }; <> IPReadError: PUBLIC ERROR [class: INT, code: ATOM, explanation: Rope.ROPE] ~ CODE; <> <<>> IPReadLog: PROC [msg: IO.STREAM, class: INT, code: ATOM, explanation: ROPE] ~ { <> IF msg=NIL THEN { SELECT class FROM InterpressInterpreter.classMasterError, InterpressInterpreter.classAppearanceError => ERROR IPReadError[class, code, explanation]; InterpressInterpreter.classMasterWarning, InterpressInterpreter.classAppearanceWarning, InterpressInterpreter.classComment => NULL; -- ignore those ENDCASE => ERROR IPReadError[class, code, explanation]; } ELSE { msg.PutRope[ 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: "] ]; msg.PutRope[explanation]; msg.PutRope[" . . . "]; }; }; InterpressToPress: PUBLIC PROC [inputName: Rope.ROPE, context: Imager.Context, beginPage, endPage: ProgressProc, msg: IO.STREAM] RETURNS [failed: BOOL ¬ FALSE] ~ { <> Log: InterpressInterpreter.LogProc ~ { IPReadLog[msg, class, ImagerError.AtomFromErrorCode[code], explanation]; }; input: InterpressInterpreter.Master ¬ InterpressInterpreter.Open[FileNames.ResolveRelativePath[inputName], Log]; FOR i: INT IN [1..input.pages] DO Process.CheckForAbort[]; failed ¬ beginPage[i, input.pages]; IF failed THEN EXIT; InterpressInterpreter.DoPage[master: input, page: i, context: context, log: Log]; Process.CheckForAbort[]; failed ¬ endPage[i, input.pages]; IF i # input.pages THEN ImagerPress.NewPage[context]; ENDLOOP; InterpressInterpreter.Close[input]; }; <> CH: PROC [char: CHAR] RETURNS [WORD] ~ INLINE {RETURN [ORD[char]]}; XC: PROC [set: [0..256), code: [0..256)] RETURNS [WORD] ~ {RETURN [set*256+code]}; C1: PROC [c: CHAR, set: [0..256), code: [0..256)] RETURNS [ImagerFontFilter.CharRangeMap] ~ { RETURN [[bc: CH[c], ec: CH[c], newbc: XC[set, code]]] }; classicModernEtAl: LIST OF ROPE ¬ LIST["Classic", "Modern"]; timesRomanEtAl: LIST OF LIST OF ROPE ¬ LIST[ LIST["TimesRoman", "Classic"], LIST["Helvetica", "Modern"], LIST["Gacha", "XeroxBook"], LIST["Tioga", "Classic"], LIST["Laurel", "Classic"]]; mrrEtAl: LIST OF ROPE ¬ LIST["-mrr", "-mir-italic", "-bir-bold-italic", "-brr-bold"]; alphaMap: ImagerFontFilter.CharacterCodeMap ~ LIST [ [bc: CH[' ], ec: CH['~], newbc: CH[' ]] ]; mathMap: ImagerFontFilter.CharacterCodeMap ¬ LIST [ C1['©, 0, 323B], C1['®, 0, 322B] ]; oisMap: ImagerFontFilter.CharacterCodeMap ¬ LIST [ [bc: CH['a], ec: CH['~], newbc: CH['a]], [bc: CH['.], ec: CH[']], newbc: CH['.]], [bc: CH['%], ec: CH[',], newbc: CH['%]], [bc: CH['-], ec: CH['-], newbc: XC[357B, 42B]], [bc: CH[' ], ec: CH['!], newbc: CH[' ]], [bc: CH['\"], ec: CH['\"], newbc: XC[0, 271B]], [bc: CH['#], ec: CH['#], newbc: CH['#]], [bc: CH['$], ec: CH['$], newbc: XC[0, 244B]], [bc: CH['^], ec: CH['^], newbc: XC[0, 255B]], [bc: CH['_], ec: CH['_], newbc: XC[0, 254B]], C1['\030, 357B, 45B], C1['\267, 357B, 146B], C1['\265, 41B, 172B], C1['\140, 0, 140B], C1[', 357B, 064B], C1[', 357B, 065B], ]; xc1Map: ImagerFontFilter.FontMap ¬ MakeXC1map[]; <> MakeXC1map: PROC RETURNS [f: ImagerFontFilter.FontMap] ~ { Enter: PROC [e: ImagerFontFilter.FontMapEntry] ~ {f ¬ CONS[e, f]}; FOR family: LIST OF ROPE ¬ classicModernEtAl, family.rest UNTIL family = NIL DO FOR face: LIST OF ROPE ¬ mrrEtAl, face.rest UNTIL face = NIL DO Enter[[ inputName: Rope.Cat["Xerox/Pressfonts/", family.first, face.first.Substr[0, 4]], output: LIST[[newName: Rope.Cat[xcFontBase, family.first, face.first.Substr[4]], charMap: oisMap]] ]]; ENDLOOP; ENDLOOP; FOR family: LIST OF LIST OF ROPE ¬ timesRomanEtAl, family.rest UNTIL family = NIL DO FOR face: LIST OF ROPE ¬ mrrEtAl, face.rest UNTIL face = NIL DO Enter[[ inputName: Rope.Cat["Xerox/Pressfonts/", family.first.first, face.first.Substr[0, 4]], output: LIST[[newName: Rope.Cat[xcFontBase, family.first.rest.first, face.first.Substr[4]], charMap: oisMap]], warn: TRUE ]]; ENDLOOP; ENDLOOP; Enter[[ inputName: "Xerox/Pressfonts/Logo-mrr", output: LIST[[newName: Rope.Concat[xcFontBase, "Logotypes-Xerox"], charMap: alphaMap]] ]]; Enter[[ inputName: "Xerox/Pressfonts/Math-mrr", output: LIST[[newName: Rope.Concat[xcFontBase, "Modern"], charMap: mathMap]] ]]; Enter[[ inputName: "Xerox/Pressfonts/Math-mir", output: LIST[[newName: Rope.Concat[xcFontBase, "Modern-italic"], charMap: mathMap]] ]]; }; <> PressToInterpressAction: PUBLIC ActionProc ~ { BeginPage: ProgressProc ~ {cmd.out.PutF1["[%g", IO.int[pageNumber]]}; EndPage: ProgressProc ~ {cmd.out.PutRope["] "]}; version: ROPE = GetCmdToken[cmds]; verbose: ROPE = GetCmdToken[cmds]; header: ROPE = IF Rope.Size[version] = 3 AND Rope.Fetch[version, 1] = '. THEN Rope.Cat["Interpress/Xerox/", version, " "] ELSE NIL; output: ImagerInterpress.Ref ¬ ImagerInterpress.Create[outputName, header]; xc: BOOL ¬ Rope.Size[version] = 3 AND Rope.Fetch[version, 0] < '3; [] ¬ PressToInterpress[inputName, output, BeginPage, EndPage, cmd.out, xc, verbose.Equal["verbose", FALSE]]; ImagerInterpress.Close[output]; }; InterpressToPressAction: PUBLIC ActionProc ~ { BeginPage: ProgressProc ~ {cmd.out.PutF1["[%g", IO.int[pageNumber]]}; EndPage: ProgressProc ~ {cmd.out.PutRope["] "]}; context: Imager.Context ~ ImagerPress.SimpleCreate[fileName: outputName, printerType: press]; [] ¬ InterpressToPress[inputName, context, BeginPage, EndPage, cmd.out]; ImagerPress.Close[context]; }; FindFullName: PROC [inputName: ROPE] RETURNS [ROPE] ~ { fullFName: ROPE ¬ NIL; fullFName ¬ FS.FileInfo[inputName].fullFName; RETURN [fullFName] }; 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 ¬ stream.GetTokenRope[CmdTokenBreak ! IO.EndOfStream => CONTINUE].token; }; GetFileNameToken: PROC [stream: IO.STREAM] RETURNS [rope: ROPE ¬ NIL] = { FileNameTokenBreak: 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 ¬ stream.GetTokenRope[FileNameTokenBreak ! IO.EndOfStream => CONTINUE].token; }; RealFromRope: PROC [rope: ROPE] RETURNS [real: REAL] = { oops: BOOL ¬ FALSE; real ¬ Convert.RealFromRope[rope ! Convert.Error => {oops ¬ TRUE; CONTINUE}]; IF oops THEN {oops ¬ FALSE; real ¬ Convert.IntFromRope[rope ! Convert.Error => {oops ¬ TRUE; CONTINUE}]}; IF oops THEN Complain[Rope.Concat["Number expected: ", rope]]; }; Complain: PUBLIC ERROR [complaint: ROPE] ~ CODE; ForceLower: PROC [old: CHAR] RETURNS [CHAR] ~ { RETURN [IF old IN ['A..'Z] THEN old+('a-'A) ELSE old] }; MakeOutputName: PROC [inputName: ROPE, doc: ROPE] RETURNS [ROPE] ~ { <> start: INT ¬ Rope.Index[s1: doc, s2: " to "]+4; end: INT ¬ Rope.SkipTo[s: doc, pos: start, skip: " \n\t"]; cp: FS.ComponentPositions; isAIS: BOOL ¬ Rope.Equal[Rope.Substr[doc, start, end-start], "ais", FALSE]; [inputName, cp] ¬ FS.ExpandName[inputName]; RETURN [Rope.Cat[ Rope.Translate[inputName, cp.base.start, cp.base.length, ForceLower], IF isAIS THEN NIL ELSE ".", IF isAIS THEN NIL ELSE Rope.Translate[doc, start, end-start, ForceLower] ]] }; Command: PUBLIC Commander.CommandProc ~ { refAction: REF ActionProc ~ NARROW[cmd.procData.clientData]; stream: IO.STREAM ¬ IO.RIS[cmd.commandLine]; firstToken: ROPE ¬ GetFileNameToken[stream]; quiet: BOOL ¬ Rope.Equal[firstToken, "-q", FALSE]; outputName: ROPE ¬ FileNames.ResolveRelativePath[IF quiet THEN GetFileNameToken[stream] ELSE firstToken]; secondTokenIndex: INT ¬ IO.GetIndex[stream]; gets: ROPE ¬ GetFileNameToken[stream]; inputName: ROPE ¬ NIL; IF NOT gets.Equal["_"] THEN { inputName ¬ outputName; outputName ¬ NIL; stream.SetIndex[secondTokenIndex]; } ELSE {inputName ¬ FileNames.ResolveRelativePath[GetFileNameToken[stream]]}; IF inputName = NIL THEN RETURN[result: $Failure, msg: cmd.procData.doc]; inputName ¬ FindFullName[inputName ! FS.Error => { IF error.group = user THEN {result ¬ $Failure; msg ¬ error.explanation; GOTO Quit} }]; IF outputName = NIL THEN { outputName ¬ MakeOutputName[inputName, cmd.procData.doc]; }; cmd.out.PutRope["Reading "]; cmd.out.PutRope[inputName]; cmd.out.PutRope[" . . . "]; IF quiet THEN cmd.commandLine ¬ NIL; refAction­[inputName, outputName, cmd, stream ! Complain => {result ¬ $Failure; msg ¬ complaint; GOTO Quit}; FS.Error => { IF error.group = user THEN {result ¬ $Failure; msg ¬ error.explanation; GOTO Quit} } ]; outputName ¬ FindFullName[outputName ! FS.Error => { outputName ¬ "Output file(s)"; CONTINUE}; ]; cmd.out.PutRope[outputName]; cmd.out.PutRope[" written.\n"]; EXITS Quit => NULL }; <> Commander.Register["PressToInterpress", Command, "Convert Press file to Interpress (output _ input [version])\n", NEW[ActionProc ¬ PressToInterpressAction]]; Commander.Register["InterpressToPress", Command, "Convert Interpress file to Press (output _ input)\n", NEW[ActionProc ¬ InterpressToPressAction]]; END.