<> <> <> <> <> <<>> <> <<>> DIRECTORY Commander USING [CommandProc, Register], Convert USING [RopeFromInt], FS USING [ComponentPositions, Error, ExpandName, FileInfo, Rename], Imager, ImagerBox, ImagerInterpress USING [Close, Create, DoPage, Ref], Interpress USING [DoPage, Master, Open], IO, Rope USING [Cat, Concat, Equal, Length, ROPE, Substr, ToRefText]; InterpressPageImpl: CEDAR PROGRAM IMPORTS Commander, Convert, FS, Imager, ImagerInterpress, Interpress, IO, Rope ~ BEGIN <> ROPE: TYPE ~ Rope.ROPE; <> CmdTokenBreak: 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]; }; GetCmdToken: PROC [stream: IO.STREAM] RETURNS [rope: ROPE] = { rope _ NIL; rope _ stream.GetTokenRope[CmdTokenBreak ! IO.EndOfStream => CONTINUE].token; }; ExpandedName: TYPE ~ RECORD [fullFName: ROPE, cp: FS.ComponentPositions]; ExpandName: PROC [inputName: ROPE] RETURNS [e: ExpandedName] ~ INLINE { [e.fullFName, e.cp] _ FS.ExpandName[inputName]; }; <> PageRange: TYPE ~ RECORD [startPage, nPages: INT]; SpecError: PUBLIC ERROR [offset: INT] ~ CODE; DoExtract: PUBLIC PROC [inputFile, outputFile: ROPE, pageSpec: LIST OF PageRange, log: IO.STREAM] RETURNS [success: BOOLEAN _ TRUE] ~ { logProc: PROC [class: INT, code: ATOM, explanation: ROPE] ~ { IO.PutRope[log, "\n *** Interpress Error "]; IO.PutRope[log, explanation]; success _ FALSE; }; n: ExpandedName ~ ExpandName[FS.FileInfo[inputFile].fullFName]; master: Interpress.Master ~ Interpress.Open[n.fullFName, logProc]; out: ImagerInterpress.Ref ~ ImagerInterpress.Create[outputFile]; IO.PutRope[log, "Reading "]; IO.PutRope[log, n.fullFName]; IO.PutRope[log, " . . . "]; FOR each: LIST OF PageRange _ pageSpec, each.rest UNTIL each=NIL DO pageRange: PageRange ~ each.first; FOR i: INT IN [pageRange.startPage..MIN[pageRange.startPage+pageRange.nPages-1, master.pages]] DO OnePage: PROC [context: Imager.Context] ~ {Interpress.DoPage[master, i, context, logProc]}; IO.PutF[stream: log, format: " [%g", v1: [integer[i]]]; ImagerInterpress.DoPage[out, OnePage]; IO.PutRope[self: log, r: "]"]; ENDLOOP; ENDLOOP; ImagerInterpress.Close[out]; IO.PutRope[log, " written.\n"]; }; InterpressExtractCommand: Commander.CommandProc ~ { GetToken: PROC [stream: IO.STREAM] RETURNS [token: ROPE _ NIL] = { Break: PROC [char: CHAR] RETURNS [IO.CharClass] = { IF char = '_ THEN RETURN [break]; IF char = ' OR char = ' OR char = ', OR char = '; OR char = '\n THEN RETURN [sepr]; RETURN [other]; }; token _ stream.GetTokenRope[Break ! IO.EndOfStream => CONTINUE].token; }; ParsePageSpec: PUBLIC PROC [pageSpecRope: ROPE] RETURNS [pageSpec: LIST OF PageRange, charsParsed: INT] ~ { Reverse: PROC [pageSpec: LIST OF PageRange] RETURNS [reversed: LIST OF PageRange] ~ { WHILE pageSpec # NIL DO t: LIST OF PageRange _ pageSpec; pageSpec _ t.rest; t.rest _ reversed; reversed _ t; ENDLOOP; }; text: REF TEXT ~ pageSpecRope.ToRefText; i: NAT _ 0; c: CHAR; SkipSpaces: PROC ~ {c _ ' ; WHILE i < text.length AND ((c _ text[i]) = ', OR c = ' OR c = ' OR c = '\n) DO i _ i+1 ENDLOOP}; GetChar: PROC RETURNS [CHAR] ~ {IF i < text.length THEN {i _ i+1; RETURN [text[i-1]]} ELSE RETURN ['\000]}; Int: PROC RETURNS [value: INT_0] ~ { SkipSpaces[]; IF NOT c IN ['0..'9] THEN ERROR SpecError[i]; WHILE i < text.length AND (c _ text[i]) IN ['0..'9] DO value _ value * 10 + (c-'0); i _ i+1; ENDLOOP; }; spec: LIST OF PageRange _ NIL; SkipSpaces[]; WHILE i < text.length DO SELECT text[i] FROM IN ['0..'9] => spec _ CONS[[Int[], 1], spec]; '[, '( => { open: CHAR _ GetChar[]; start: INT _ Int[]; end: INT; SkipSpaces[]; IF i < text.length AND text[i] = '. THEN i _ i+1 ELSE ERROR SpecError[i]; IF i < text.length AND text[i] = '. THEN i _ i+1 ELSE ERROR SpecError[i]; end _ Int[]; SkipSpaces[]; IF (c _ GetChar[]) = '] OR c = ') THEN { IF open = '( THEN start _ start + 1; IF c = '] THEN end _ end + 1; IF end > start THEN spec _ CONS[[start, end-start], spec] } ELSE ERROR SpecError[i]; }; ENDCASE => EXIT; SkipSpaces[]; ENDLOOP; RETURN [Reverse[spec], i] }; stream: IO.STREAM _ IO.RIS[cmd.commandLine]; outputName: ROPE _ GetToken[stream]; inputName: ROPE; pagesToken: ROPE; pageSpec: LIST OF PageRange; IF outputName.Length = 0 THEN {cmd.out.PutRope["Output file missing.\n"]; RETURN}; IF NOT GetToken[stream].Equal["_"] THEN {cmd.out.PutRope["Missing \"_\".\n"]; RETURN}; inputName _ GetToken[stream]; pagesToken _ GetToken[stream]; IF pagesToken.Equal["PAGE", FALSE] OR pagesToken.Equal["PAGES", FALSE] THEN { skip: INT; [pageSpec, skip] _ ParsePageSpec[cmd.commandLine.Substr[stream.GetIndex]]; stream.SetIndex[stream.GetIndex+skip]; } ELSE pageSpec _ LIST[[1, 1000000]]; IF NOT DoExtract[inputName, outputName, pageSpec, cmd.out] THEN { cmd.out.PutRope["Unable to extract any pages from "]; cmd.out.PutRope[inputName]; cmd.out.PutChar['\n]; } ELSE {cmd.out.PutRope[outputName]; cmd.out.PutRope[" Written.\n"]}; IF NOT stream.EndOf THEN {cmd.out.PutRope["Ignored: "]; cmd.out.PutRope[cmd.commandLine.Substr[stream.GetIndex]]; cmd.out.PutChar['\n]}; }; <> DoBreakup: PROC [inputName: ROPE, log: IO.STREAM] ~ { logProc: PROC [class: INT, code: ATOM, explanation: ROPE] ~ { IO.PutRope[log, "\n *** Interpress Error "]; IO.PutRope[log, explanation]; }; n: ExpandedName ~ ExpandName[FS.FileInfo[inputName].fullFName]; base: ROPE ~ Rope.Substr[n.fullFName, n.cp.base.start, n.cp.base.length]; ext: ROPE ~ Rope.Substr[n.fullFName, n.cp.ext.start, n.cp.ext.length]; master: Interpress.Master ~ Interpress.Open[n.fullFName, logProc]; IO.PutRope[log, "Reading "]; IO.PutRope[log, n.fullFName]; IO.PutRope[log, " . . . "]; FOR i: INT IN [1..master.pages] DO name: ROPE ~ Rope.Cat[base, "-", Convert.RopeFromInt[i], ".", ext]; out: ImagerInterpress.Ref ~ ImagerInterpress.Create[name]; onePage: PROC [context: Imager.Context] ~ {Interpress.DoPage[master, i, context, logProc]}; IO.PutRope[log, FS.FileInfo[name].fullFName]; ImagerInterpress.DoPage[out, onePage]; IO.PutRope[log, " "]; ImagerInterpress.Close[out]; ENDLOOP; IO.PutRope[log, "written.\n"]; }; InterpressBreakupCommand: Commander.CommandProc ~ { stream: IO.STREAM _ IO.RIS[cmd.commandLine]; inputName: ROPE _ GetCmdToken[stream]; IF inputName = NIL THEN RETURN[result: $Failure, msg: cmd.procData.doc]; DoBreakup[inputName, cmd.out ! FS.Error => IF error.group = user THEN {result _ $Failure; msg _ error.explanation; CONTINUE}]; }; <> DoClip: PROC [inputName: ROPE, r: Imager.Rectangle, log: IO.STREAM] ~ { logProc: PROC [class: INT, code: ATOM, explanation: ROPE] ~ { IO.PutRope[log, "\n *** Interpress Error "]; IO.PutRope[log, explanation]; }; name: ROPE; n: ExpandedName ~ ExpandName[FS.FileInfo[inputName].fullFName]; base: ROPE ~ Rope.Substr[n.fullFName, 0, n.cp.base.start+n.cp.base.length]; ext: ROPE ~ Rope.Substr[n.fullFName, n.cp.ext.start, n.cp.ext.length]; master: Interpress.Master ~ Interpress.Open[n.fullFName, logProc]; IO.PutRope[log, "Reading "]; IO.PutRope[log, n.fullFName]; IO.PutRope[log, " . . . "]; name _ Rope.Cat[base, "-", "Clipped"]; IF n.cp.ext.length # 0 THEN name _ Rope.Cat[name, ".", ext]; { out : ImagerInterpress.Ref ~ ImagerInterpress.Create[name]; onePage: PROC [context: Imager.Context] ~ { context.ClipRectangle[r]; Interpress.DoPage[master, 1, context, logProc]; }; IO.PutRope[log, FS.FileInfo[name].fullFName]; ImagerInterpress.DoPage[out, onePage]; IO.PutRope[log, " "]; ImagerInterpress.Close[out]; IO.PutRope[log, "written.\n"]; }; }; InterpressClipCommand: Commander.CommandProc ~ { stream: IO.STREAM _ IO.RIS[cmd.commandLine]; inputName: ROPE _ GetCmdToken[stream]; r: Imager.Rectangle; IF inputName = NIL THEN RETURN[result: $Failure, msg: cmd.procData.doc]; r.x _ IO.GetReal[stream]; r.y _ IO.GetReal[stream]; r.w _ IO.GetReal[stream]; r.h _ IO.GetReal[stream]; DoClip[inputName, r, cmd.out ! FS.Error => IF error.group = user THEN {result _ $Failure; msg _ error.explanation; CONTINUE}]; }; <> DoConcatenate: PROC [outputName: ROPE, cmdLineStream: IO.STREAM, log: IO.STREAM] ~ { pageNumber: INT _ 0; logProc: PROC [class: INT, code: ATOM, explanation: ROPE] ~ { IO.PutRope[log, "\n *** Interpress Error "]; IO.PutRope[log, explanation]; }; n: ExpandedName ~ ExpandName[outputName]; extendedName: ROPE ~ IF n.cp.ext.length = 0 THEN Rope.Substr[n.fullFName, 0, n.cp.base.start+n.cp.base.length].Concat[".interpress"] ELSE n.fullFName; tempName: ROPE _ "TempConcatenation.interpress"; <> out: ImagerInterpress.Ref ~ ImagerInterpress.Create[tempName]; tempName _ FS.FileInfo[tempName].fullFName; IO.PutRope[log, "Reading "]; FOR inputName: ROPE _ GetCmdToken[cmdLineStream], GetCmdToken[cmdLineStream] UNTIL inputName = NIL DO fullInputName: ROPE ~ FS.FileInfo[inputName].fullFName; master: Interpress.Master ~ Interpress.Open[fullInputName, logProc]; IO.PutRope[log, fullInputName]; IO.PutRope[log, " "]; FOR i: INT IN [1..master.pages] DO onePage: PROC [context: Imager.Context] ~ {Interpress.DoPage[master, i, context, logProc]}; IO.PutRope[log, "["]; IO.PutRope[log, Convert.RopeFromInt[pageNumber _ pageNumber + 1]]; ImagerInterpress.DoPage[out, onePage]; IO.PutRope[log, "] "]; ENDLOOP; ENDLOOP; ImagerInterpress.Close[out]; FS.Rename[from: tempName, to: extendedName]; IO.PutRope[log, FS.FileInfo[extendedName].fullFName]; IO.PutRope[log, " written.\n"]; }; InterpressConcatenateCommand: Commander.CommandProc ~ { stream: IO.STREAM _ IO.RIS[cmd.commandLine]; outputName: ROPE _ GetCmdToken[stream]; gets: ROPE _ GetCmdToken[stream]; IF outputName = NIL OR NOT gets.Equal["_"] THEN RETURN[result: $Failure, msg: cmd.procData.doc]; DoConcatenate[outputName, stream, cmd.out ! FS.Error => IF error.group = user THEN {result _ $Failure; msg _ error.explanation; CONTINUE}]; }; <> Commander.Register[key: "InterpressExtract", proc: InterpressExtractCommand, doc: "Extract pages from interpress files, e.g. result.ip _ source.ip PAGES 1, 3, [10..15]"]; Commander.Register[key: "IPExtract", proc: InterpressExtractCommand, doc: "Extract pages from interpress files, e.g. result.ip _ source.ip PAGES 1, 3, [10..15] (alias for InterpressExtract)"]; Commander.Register[key: "InterpressBreakup", proc: InterpressBreakupCommand, doc: "Breaks an interpress master into a collection of one-page interpress masters"]; Commander.Register[key: "InterpressClip", proc: InterpressClipCommand, doc: "Clips a single page Interpress master to a specified rectangle: x, y, w, h"]; Commander.Register[key: "IPBreakup", proc: InterpressBreakupCommand, doc: "Breaks an interpress master into a collection of one-page interpress masters (alias for InterpressBreakup)"]; Commander.Register[key: "InterpressConcatenate", proc: InterpressConcatenateCommand, doc: "Concatenates a collection of Interpress masters into one. (output _ input1 input2 . . .)"]; Commander.Register[key: "IPConcatenate", proc: InterpressConcatenateCommand, doc: "Concatenates a collection of Interpress masters into one. (output _ input1 input2 . . .) (alias for InterpressConcatenate)"]; END.