InterpressToTiogaArtworkImpl.mesa
Copyright © 1984, 1985, 1986 by Xerox Corporation. All rights reserved.
Michael Plass, September 6, 1985 6:00:32 pm PDT
Doug Wyatt, June 6, 1986 2:40:30 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
ActionProc:
TYPE ~
PROC [data: ParsedCommand, cmd: Commander.Handle];
LogError:
PROC [msg:
IO.
STREAM, class:
INT, code:
ATOM, explanation:
ROPE] ~ {
msg.PutRope[
SELECT class
FROM
Interpress.classMasterError => "Master Error: ",
Interpress.classMasterWarning => "Master Warning: ",
Interpress.classAppearanceError => "Appearance Error: ",
Interpress.classAppearanceWarning => "Appearance Warning: ",
Interpress.classComment => "Comment: ",
ENDCASE => NIL
];
msg.PutRope[explanation];
msg.PutRope[" . . . "];
};
Error:
ERROR [rope:
ROPE] ~
CODE;
GetIPFragment:
PROC [data: ParsedCommand, cmd: Commander.Handle]
RETURNS [
ROPE] ~ {
Log: Interpress.LogProc ~ { LogError[cmd.out, class, code, explanation] };
inputMaster: Interpress.Master ~ Interpress.Open[data.inputName, Log];
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, page: data.page, context: context, log: Log];
};
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: BOOL ← FALSE;
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: ROPE ← NIL;
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: REAL ← IO.GetReal[stream];
unit: ROPE ← GetName[stream];
multipler:
REAL ←
SELECT
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: ROPE ← NIL,
page: INT ← 1,
pageHeight, pageWidth, topMargin, leftMargin, height, depth, width, topSpace, bottomSpace: REAL ← 0.0,
scale: REAL ← 1.0,
clip: BOOL ← FALSE
];
Parse:
PROC [stream:
IO.
STREAM]
RETURNS [data: ParsedCommand] ~ {
outputName: ROPE ← GetCmdToken[stream];
secondTokenIndex: INT ← stream.GetIndex;
gets: ROPE ← GetCmdToken[stream];
inputName: ROPE ← NIL;
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.STREAM ← IO.RIS[cmd.commandLine];
refAction: REF ActionProc ~ NARROW[cmd.procData.clientData];
data: ParsedCommand;
data ← Parse[stream !
ParseError => {
start: INT ← MAX[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.