InterpressToTiogaArtworkImpl.mesa
Copyright © 1984, 1985 by Xerox Corporation. All rights reserved.
Michael Plass, September 6, 1985 6:00:32 pm PDT
DIRECTORY Atom, ViewerClasses, TiogaMenuOps, Convert, Commander, FS, Imager, ImagerInterpress, Interpress, IO, Rope, TiogaAccess;
InterpressToTiogaArtworkImpl: CEDAR PROGRAM
IMPORTS TiogaMenuOps, Convert, Commander, FS, Imager, ImagerInterpress, Interpress, IO, Rope, TiogaAccess
~ BEGIN
ROPE: TYPE ~ Rope.ROPE;
ActionProc: TYPE ~ PROC [data: ParsedCommand, cmd: Commander.Handle];
Log: Interpress.LogProc ~ {
cmd: Commander.Handle ~ NARROW[master.logData];
msg: IO.STREAM ~ cmd.out;
msg.PutRope[
SELECT class FROM
masterError => "Master Error: ",
masterWarning => "Master Warning: ",
appearanceError => "Appearance Error: ",
appearanceWarning => "Appearance Warning: ",
comment => "Comment: ",
ENDCASE => NIL
];
msg.PutRope[explanation];
msg.PutRope[" . . . "];
};
Error: ERROR [rope: ROPE] ~ CODE;
GetIPFragment: PROC [data: ParsedCommand, cmd: Commander.Handle] RETURNS [ROPE] ~ {
inputMaster: Interpress.OpenMaster ~ Interpress.Open[data.inputName, Log, cmd];
ros: IO.STREAM ~ IO.ROS[];
outputMaster: ImagerInterpress.Ref ~ ImagerInterpress.CreateFromStream[ros, "Interpress/Xerox/3.0 "];
action: PROC [context: Imager.Context] ~ {
IF data.scale # 1.0 THEN Imager.ScaleT[context, data.scale];
IF data.clip THEN Imager.ClipRectangle[context, [0, -data.depth, data.width, data.height+data.depth]];
Imager.TranslateT[context, [-data.leftMargin, data.topMargin-data.pageHeight+data.height]];
Interpress.DoPage[master: inputMaster, context: context, page: data.page];
};
IF data.page NOT IN [1..inputMaster.pages] THEN Error["Page number out of range"];
ImagerInterpress.DoPage[outputMaster, action, 1.0];
ImagerInterpress.Finish[outputMaster];
RETURN [IO.RopeFromROS[ros]];
};
vanillaTC: TiogaAccess.TiogaChar ~ [
charSet: 0,
char: '\n,
looks: ALL[FALSE],
format: $default,
comment: FALSE,
endOfNode: FALSE,
deltaLevel: 0,
propList: NIL
];
InterpressToTiogaArtworkAction: PROC [data: ParsedCommand, cmd: Commander.Handle] ~ {
ipFragment: ROPE ~ GetIPFragment[data, cmd];
writer: TiogaAccess.Writer ← TiogaAccess.Create[];
tc: TiogaAccess.TiogaChar ← [
charSet: 0,
char: '\n,
looks: ALL[FALSE],
format: $default,
comment: TRUE,
endOfNode: FALSE,
deltaLevel: 1,
propList: NIL
];
PutRope: PROC [rope: ROPE] ~ {
action: Rope.ActionType ~ {tc.char ← c; TiogaAccess.Put[writer, tc]};
[] ← Rope.Map[base: rope, action: action];
};
PutLooksRope: PROC [rope: ROPE, look1, look2: CHAR ← '\000] ~ {
save: TiogaAccess.Looks ~ tc.looks;
IF look1 # '\000 THEN tc.looks[look1] ← TRUE;
IF look2 # '\000 THEN tc.looks[look2] ← TRUE;
PutRope[rope];
tc.looks ← save;
};
PutRopeProp: PROC [key: ATOM, val: ROPE] ~ {
tc.propList ← CONS[NEW[Atom.DottedPairNode ← [key: key, val: val]], tc.propList];
};
sepNeeded: BOOLFALSE;
Sp: PROC ~ {PutRope[" "]; sepNeeded ← FALSE};
Comma: PROC ~ {IF sepNeeded THEN PutRope[", "]; sepNeeded ← FALSE};
Putmm: PROC [meters: REAL] ~ {
PutLooksRope[Convert.RopeFromReal[meters*1000], 'f];
PutLooksRope["mm", 's, 'o];
sepNeeded ← TRUE;
};
PutKey: PROC [rope: ROPE] ~ {
Comma[];
PutLooksRope[rope, 'o];
PutLooksRope[": ", 'o];
sepNeeded ← TRUE;
};
PutKeyMeters: PROC [name: ROPE, meters, defaultMeters: REAL] ~ {
IF meters#defaultMeters THEN {PutKey[name]; Putmm[meters]};
};
tc.endOfNode ← TRUE; PutRope["\n"]; tc.endOfNode ← FALSE;
PutLooksRope["Interpress Artwork", 'n];
PutRope[": "];
PutRope[data.inputName]; Sp[];
PutKeyMeters["pageHeight", data.pageHeight, default.pageHeight];
PutKeyMeters["pageWidth", data.pageWidth, default.pageWidth];
PutKeyMeters["topMargin", data.topMargin, default.topMargin];
PutKeyMeters["height", data.height, default.height];
PutKeyMeters["depth", data.depth, default.depth];
PutKeyMeters["width", data.width, default.width];
PutKeyMeters["topSpace", data.topSpace, default.topSpace];
PutKeyMeters["bottomSpace", data.bottomSpace, default.bottomSpace];
IF data.page#default.page THEN {PutKey["page"]; PutLooksRope[Convert.RopeFromInt[data.page], 'f]};
IF data.scale#default.scale THEN {PutKey["scale"]; PutLooksRope[Convert.RopeFromReal[data.scale], 'f]};
IF data.clip THEN {PutKey["clip"]; PutLooksRope["TRUE", 'o, 's]};
PutRopeProp[$Postfix, Rope.Cat[
Convert.RopeFromReal[(data.height+data.topSpace)*1000*data.scale], " mm topLeading ",
Convert.RopeFromReal[(data.height+data.topSpace)*1000*data.scale], " mm topIndent " ].Cat[
Convert.RopeFromReal[(data.depth+data.bottomSpace)*1000*data.scale], " mm bottomLeading ",
Convert.RopeFromReal[data.width*1000*data.scale], " mm lineLength "
]];
PutRopeProp[$Bounds, Rope.Cat[
Convert.RopeFromReal[-data.depth*1000*data.scale], " mm ymin ",
Convert.RopeFromReal[data.width*1000*data.scale], " mm xmax " ].Cat[
Convert.RopeFromReal[data.height*1000*data.scale], " mm ymax "
]];
PutRopeProp[$Artwork, "Interpress"];
PutRopeProp[$Interpress, ipFragment];
tc.endOfNode ← TRUE;
tc.deltaLevel ← 1;
tc.char ← '\n;
TiogaAccess.Put[writer, tc];
tc ← vanillaTC;
PutRope[" Insert caption here "];
tc.endOfNode ← TRUE;
tc.char ← '\n;
tc.format ← $caption;
TiogaAccess.Put[writer, tc];
IF data.outputName # NIL THEN {
TiogaAccess.WriteFile[writer, data.outputName];
}
ELSE {
wdstar: ROPE ~ FS.ExpandName["*"].fullFName;
wd: ROPE ~ wdstar.Substr[0, wdstar.Size-1];
viewer: ViewerClasses.Viewer ← TiogaMenuOps.Open[wd];
TiogaAccess.WriteViewer[writer, viewer];
};
};
FindFullName: PROC [inputName: ROPE] RETURNS [ROPE] ~ {
fullFName: ROPENIL;
fullFName ← FS.FileInfo[inputName].fullFName;
RETURN [fullFName]
};
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;
};
NameBreak: PROC [char: CHAR] RETURNS [IO.CharClass] = {
IF char = ': OR char = '= OR char = '~ THEN RETURN [break];
IF char = ' OR char = '  OR char = ', OR char = '; OR char = '\n THEN RETURN [sepr];
RETURN [other];
};
GetName: PROC [stream: IO.STREAM] RETURNS [name: ROPE] ~ {
name ← NIL;
name ← IO.GetTokenRope[stream, NameBreak ! IO.EndOfStream => CONTINUE].token;
};
ParseError: ERROR [msg: ROPE, index: INT] ~ CODE;
RaiseParseError: PROC [stream: IO.STREAM, msg: ROPE] ~ {
ERROR ParseError[msg, stream.GetIndex];
};
GetMeters: PROC [stream: IO.STREAM] RETURNS [REAL] = {
r: REALIO.GetReal[stream];
unit: ROPE ← GetName[stream];
multipler: REALSELECT TRUE FROM
unit.Equal["in"] => 0.0254,
unit.Equal["pt"] => 0.0254/72.27,
unit.Equal["cm"] => 0.01,
unit.Equal["mm"] => 0.001,
unit.Equal["bp"] => 0.0254/72.0,
ENDCASE => 0.0;
IF multipler = 0.0 THEN RaiseParseError[stream, "Unknown unit: "];
RETURN [r*multipler];
};
ParsedCommand: TYPE ~ REF ParsedCommandRep;
ParsedCommandRep: TYPE ~ RECORD [
outputName, inputName: ROPENIL,
page: INT ← 1,
pageHeight, pageWidth, topMargin, leftMargin, height, depth, width, topSpace, bottomSpace: REAL ← 0.0,
scale: REAL ← 1.0,
clip: BOOLFALSE
];
Parse: PROC [stream: IO.STREAM] RETURNS [data: ParsedCommand] ~ {
outputName: ROPE ← GetCmdToken[stream];
secondTokenIndex: INT ← stream.GetIndex;
gets: ROPE ← GetCmdToken[stream];
inputName: ROPENIL;
IF NOT gets.Equal["←"] THEN {
inputName ← outputName;
outputName ← NIL;
stream.SetIndex[secondTokenIndex];
}
ELSE {inputName ← GetCmdToken[stream]};
IF inputName = NIL THEN RaiseParseError[stream, docRope];
inputName ← FindFullName[inputName];
data ← NEW[ParsedCommandRep ← default];
data.outputName ← outputName;
data.inputName ← inputName;
DO
keyword: ROPE ← GetName[stream];
colon: ROPE ← GetName[stream];
c: CHAR ← '\000;
IF keyword = NIL THEN EXIT;
IF colon.Size = 1 AND ((c𡤌olon.Fetch[0])=': OR c='= OR c = '~) THEN NULL
ELSE RaiseParseError[stream, "Colon expected after keyword: "];
SELECT TRUE FROM
keyword.Equal["Page", FALSE] => data.page ← IO.GetInt[stream];
keyword.Equal["PageHeight", FALSE] => data.pageHeight ← GetMeters[stream];
keyword.Equal["PageWidth", FALSE] => data.pageWidth ← GetMeters[stream];
keyword.Equal["TopMargin", FALSE] => data.topMargin ← GetMeters[stream];
keyword.Equal["LeftMargin", FALSE] => data.leftMargin ← GetMeters[stream];
keyword.Equal["Height", FALSE] => data.height ← GetMeters[stream];
keyword.Equal["Depth", FALSE] => data.depth ← GetMeters[stream];
keyword.Equal["Width", FALSE] => data.width ← GetMeters[stream];
keyword.Equal["Scale", FALSE] => data.scale ← IO.GetReal[stream];
keyword.Equal["Clip", FALSE] => data.clip ← IO.GetBool[stream];
ENDCASE => RaiseParseError[stream, "Unknown keyword parameter: "];
ENDLOOP;
};
Command: Commander.CommandProc ~ {
stream: IO.STREAMIO.RIS[cmd.commandLine];
refAction: REF ActionProc ~ NARROW[cmd.procData.clientData];
data: ParsedCommand;
data ← Parse[stream !
ParseError => {
start: INTMAX[index-10, 0];
cmd.out.PutRope[msg];
IF start > 0 THEN cmd.out.PutRope["..."];
cmd.out.PutRope[cmd.commandLine.Substr[start, index-start]];
IF index > 1 THEN cmd.out.PutRope["..."];
cmd.out.PutRope["\n"];
GOTO Quit
};
FS.Error => {
cmd.out.PutRope[error.explanation];
cmd.out.PutRope["\n"];
GOTO Quit
};
];
IF data.height*data.scale > maxSafeHeight THEN {
cmd.out.PutRope["Warning: height is too large for proper refresh\n"];
};
IF data.depth*data.scale > maxSafeDepth THEN {
cmd.out.PutRope["Warning: depth is too large for proper refresh\n"];
};
cmd.out.PutRope["Reading "];
cmd.out.PutRope[data.inputName];
cmd.out.PutRope[" . . . "];
refAction^[data, cmd ! Error => {
cmd.out.PutRope[rope];
cmd.out.PutRope["\n"];
GOTO Quit
}];
IF data.outputName # NIL THEN {
data.outputName ← FindFullName[data.outputName];
cmd.out.PutRope[data.outputName];
cmd.out.PutRope[" written.\n"];
}
ELSE cmd.out.PutRope[" ok.\n"];
EXITS Quit => {}
};
inch: REAL ~ 0.0254;
bp: REAL ← inch/72.0;
maxSafeHeight: REAL ← 512*bp;
maxSafeDepth: REAL ← 128*bp;
default: ParsedCommandRep ← [
page: 1, topMargin: 1*inch, pageHeight: 11*inch, pageWidth: 8.5*inch, leftMargin: 1*inch, height: 9*inch, depth: 0*inch, width: 6.5*inch, topSpace: 4*bp, bottomSpace: 8*bp, scale: 1.0, clip: FALSE
];
docRope: ROPE ~
"[<output> ←] <input> page: 1, topMargin: 1 in, leftMargin: 1 in, height: 9 in, depth: 0 in, width: 6.5 in, scale: 1, topSpace: 4 bp, bottomSpace: 8 bp, clip: FALSE";
Commander.Register["InterpressToTiogaArtwork", Command, Rope.Cat["Convert Interpress file to Tioga\n ", docRope, "\n"], NEW[ActionProc ← InterpressToTiogaArtworkAction]];
END.