InkJetPrint.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Last Edited: Rumph, May 22, 1984 5:40:07 pm PDT
Nickell, June 11, 1985 11:30:45 am PDT
Tim Diebert: September 20, 1985 1:51:12 pm PDT
DIRECTORY
AIS,
Basics USING [DivMod],
Commander USING [CommandProc, Register],
CommandTool USING [ParseToList],
Convert USING [RealFromRope],
DiabloStreams USING [StreamOpen],
FS USING [StreamOpen],
IO USING [STREAM, CR, ESC, LF, SP, char, card, Close, EndOfStream, GetChar, Put, PutChar, PutRope, Reset, rope],
Process USING [CheckForAbort],
Real USING [FixI],
Rope USING [ROPE, Concat, Fetch, Length],
UserProfile USING [Boolean, Number];
InkJetPrint: CEDAR PROGRAM IMPORTS AIS, Basics, Commander, CommandTool, Convert, DiabloStreams, FS, IO, Process, Real, Rope, UserProfile = TRUSTED BEGIN
ROPE: TYPE = Rope.ROPE;
Side: TYPE = {left, right};
PrimaryColor: TYPE = {cyan, magenta, yellow, black};
displayRasterPart: TYPE = AIS.RasterPart ← [
scanCount: 100,
scanLength: 100,
scanMode: rd,
bitsPerPixel: 8,
linesPerBlock: -1, -- for blocked AIS files. -1=no blocks
paddingPerBlock: 0 --in words
];
displayRaster: AIS.Raster ← NEW[displayRasterPart];
OpenAIS: PROCEDURE [name: ROPE] RETURNS [window: AIS.WRef] = TRUSTED {
file: AIS.FRef ← AIS.OpenFile[name ! ANY => GOTO Exit];
window ← AIS.OpenWindow[file ! ANY => {AIS.CloseFile[file] ; GOTO Exit}];
EXITS
Exit => RETURN[NIL]
};
Closes a file and window
CloseAIS: PROCEDURE [window: AIS.WRef] = TRUSTED {
file: AIS.FRef;
IF window=NIL THEN RETURN;
file ← window.fref;
AIS.CloseWindow[window];
window ← NIL;
AIS.CloseFile[file];
file ← NIL;
};
SetMargin: SAFE PROC [stream: IO.STREAM, arg: CARDINAL, side: Side ← left] ~ TRUSTED {
OPEN IO;
Put[stream, char[ESC], char[IF side = left THEN 'l ELSE 'r], card[arg]];
Put[stream, char[CR]];
};
MicroLine: TYPE ~ [0..4);
MaxChars: CARDINAL ~ 200;
Buffer: TYPE ~ PACKED ARRAY [0..MaxChars*8) OF BOOLEAN; --Kluge
CBuffer: TYPE ~ PACKED ARRAY [0..MaxChars) OF CHAR;  --Same size as Buffer!!!
Band: TYPE ~ ARRAY PrimaryColor OF ARRAY MicroLine OF Buffer;
emptyBuffer: Buffer ← ALL[FALSE];
graphicsChar: ARRAY PrimaryColor OF ARRAY MicroLine OF CHAR ~ [
cyan: ['<, '=, '>, '?],
magenta: ['4, '5, '6, '7],
yellow: ['8, '9, ':, ';],
black: ['0, '1, '2, '3]
];
DoIt: PROC [name: ARRAY PrimaryColor OF ROPE, stream: IO.STREAM, lMarg, pWidth: REAL, which: ARRAY PrimaryColor OF BOOLALL[TRUE]] ~ TRUSTED {
OPEN IO;
window: ARRAY PrimaryColor OF AIS.WRef ← ALL[NIL];
totalLength: CARDINAL;
imageWidth: INTEGER;
leftMargin: INTEGER ← Real.FixI[10.0 * lMarg];
printWidth: INTEGER ← Real.FixI[10.0 * pWidth];
inchesPerPage: INT ~ UserProfile.Number["Diablo.PageSize", 11];
verticalCenter: BOOL ~ UserProfile.Boolean["Diablo.VerticalCenter", TRUE];
FOR color: PrimaryColor IN PrimaryColor DO
IF which[color] THEN window[color] ← OpenAIS[name[color]];
IF window[color]#NIL THEN displayRaster ← AIS.ReadRaster[window[color].fref];
ENDLOOP;
imageWidth ← (displayRaster.scanLength + 11) / 12; -- next greater 1/10 inch
IO.PutRope[stream, "\033\015P"];  --Reset the terminal
IO.Put[stream, rope["\033\014"], char[LOOPHOLE[CARDINAL[inchesPerPage]*6]]]; --Set page length
IF verticalCenter THEN {  --Do vertical centering
totalMicrolines: CARDINAL ~ (inchesPerPage*30 - displayRaster.scanCount/4)/2;
lfs, microlines: CARDINAL;  --A lf is 1/6'', while microline is 1/30''.
[lfs, microlines] ← Basics.DivMod[totalMicrolines, 5];
THROUGH [1..lfs] DO IO.PutChar[stream, LF] ENDLOOP;
THROUGH [1..microlines] DO IO.PutRope[stream, "\033k1"] ENDLOOP;
};
SetMargin[ -- set the left margin
stream: stream,
arg: leftMargin + MAX[0, (printWidth - imageWidth) / 2],
side: left
];
SetMargin[ -- set the right margin
stream: stream,
arg: leftMargin + printWidth, -- let the printer truncate the image past the width
side: right
];
totalLength ← (displayRaster.scanLength+7) / 8;
FOR startLine: CARDINAL ← 0, startLine+4 WHILE startLine < displayRaster.scanCount DO
PrintBand: PROC ~ TRUSTED {
FOR color: PrimaryColor IN PrimaryColor DO
IF window[color]=NIL THEN LOOP;
FOR line: MicroLine IN MicroLine DO
cBuffer: CBuffer ~ LOOPHOLE[band[color][line]];
Put[stream, char[ESC], char['g], char[graphicsChar[color][line]]];
Put[stream, card[totalLength], char[SP]];
FOR char: CARDINAL IN [0..totalLength] DO
PutChar[stream, cBuffer[char]];
ENDLOOP;
ENDLOOP;
ENDLOOP;
Put[stream, char[ESC], char['k], char['1]];
Process.CheckForAbort[];
};
band: Band ← ALL[ALL[emptyBuffer]];
FOR line: CARDINAL IN [startLine..MIN[displayRaster.scanCount-1, startLine+3]] DO
microLine: CARDINAL ← line-startLine;
FOR color: PrimaryColor IN PrimaryColor DO
IF window[color]=NIL THEN LOOP;
FOR pixel: CARDINAL IN [0..displayRaster.scanLength) DO
IF AIS.ReadSample[window[color], line, pixel]>0 THEN band[color][microLine][pixel] ← TRUE;
ENDLOOP;
ENDLOOP;
ENDLOOP;
PrintBand[];
ENDLOOP;
IF verticalCenter THEN IO.PutChar[stream, '\014]; --Form feed to next page
IO.Close[stream];
FOR color: PrimaryColor IN PrimaryColor DO
CloseAIS[window[color]];
ENDLOOP;
};
Print: Commander.CommandProc = TRUSTED {
s: IO.STREAM ~ DiabloStreams.StreamOpen[];
{
ENABLE ABORTED => IF s#NIL THEN {IO.Reset[s]; IO.Close[s]};
DO
IO.PutChar[s, IO.GetChar[cmd.in ! IO.EndOfStream => EXIT]];
Process.CheckForAbort[];
ENDLOOP;
IO.Close[s];
};
};
FilePrint: Commander.CommandProc = TRUSTED {
fileList: LIST OF ROPE;
length: INT;
s: IO.STREAM ~ DiabloStreams.StreamOpen[];
out: IO.STREAM;
[fileList, length] ← CommandTool.ParseToList[cmd: cmd];
out ← FS.StreamOpen[fileList.first];
{
ENABLE UNWIND => {IF s#NIL THEN {IO.Reset[s]; IO.Close[s]}; IF out#NIL THEN {IO.Close[out]}};
DO
IO.PutChar[s, IO.GetChar[out ! IO.EndOfStream => EXIT]];
Process.CheckForAbort[];
ENDLOOP;
IO.Close[out];
IO.Close[s];
};
};
MakeFile: Commander.CommandProc = TRUSTED {
fileList: LIST OF ROPE;
length: INT;
which: ARRAY PrimaryColor OF BOOLALL[TRUE];
s: IO.STREAMNIL;
[fileList, length] ← CommandTool.ParseToList[cmd: cmd];
IF length=0 THEN RETURN [msg: "Usage: IJMake [-cmyb] inFileNameRoot [leftMarg [printWidth]]"];
IF Rope.Fetch[fileList.first]='- THEN {
rope: ROPE ~ fileList.first;
fileList ← fileList.rest;
length ← length - 1;
which ← ALL[FALSE];
FOR i: CARDINAL IN [1..CARDINAL[Rope.Length[rope]]) DO
SELECT Rope.Fetch[rope, i] FROM
'c => which[cyan] ← TRUE;
'm => which[magenta] ← TRUE;
'y => which[yellow] ← TRUE;
'b => which[black] ← TRUE;
ENDCASE;
ENDLOOP;
};
BEGIN ENABLE UNWIND => IF s#NIL THEN IO.Close[s];
DoIt[
[Rope.Concat[fileList.first, "-cyan.ais"], Rope.Concat[fileList.first, "-mag.ais"], Rope.Concat[fileList.first, "-yel.ais"], Rope.Concat[fileList.first, "-black.ais"]],
(s ← FS.StreamOpen[Rope.Concat[fileList.first, ".c150"], create]),
IF length > 1
THEN Convert.RealFromRope[fileList.rest.first]
ELSE 0.5, -- default the left margin to 0.5 inch
IF length > 2
THEN Convert.RealFromRope[fileList.rest.rest.first]
ELSE 8.0, -- default the width to 8" from left
which
];
END;
};
Make: Commander.CommandProc = TRUSTED {
fileList: LIST OF ROPE;
length: INT;
which: ARRAY PrimaryColor OF BOOLALL[TRUE];
[fileList, length] ← CommandTool.ParseToList[cmd: cmd];
IF length=0 THEN RETURN [msg: "Usage: IJMake [-cmyb] inFileNameRoot [leftMarg [printWidth]]"];
IF Rope.Fetch[fileList.first]='- THEN {
rope: ROPE ~ fileList.first;
fileList ← fileList.rest;
length ← length - 1;
which ← ALL[FALSE];
FOR i: CARDINAL IN [1..CARDINAL[Rope.Length[rope]]) DO
SELECT Rope.Fetch[rope, i] FROM
'c => which[cyan] ← TRUE;
'm => which[magenta] ← TRUE;
'y => which[yellow] ← TRUE;
'b => which[black] ← TRUE;
ENDCASE;
ENDLOOP;
};
DoIt[
[Rope.Concat[fileList.first, "-cyan.ais"], Rope.Concat[fileList.first, "-mag.ais"], Rope.Concat[fileList.first, "-yel.ais"], Rope.Concat[fileList.first, "-black.ais"]],
cmd.out,
IF length > 1
THEN Convert.RealFromRope[fileList.rest.first]
ELSE 0.5, -- default the left margin to 0.5 inch
IF length > 2
THEN Convert.RealFromRope[fileList.rest.rest.first]
ELSE 8.0, -- default the width to 8" from left
which
];
};
Commander.Register[
key: "FilePrint",
proc: FilePrint,
doc: "FilePrint -- print file to Diablo C150."];
Commander.Register[
key: "IJPrint",
proc: Print,
doc: "IJPrint -- print piped input stream the to Diablo C150."];
Commander.Register[
key: "IJMake",
proc: Make,
doc: "IJMake [-cmyb] inFileNameRoot [leftMarg [printWidth]] -- Create file for Diablo C150 from AIS sources."];
Commander.Register[
key: "MakeFile",
proc: MakeFile,
doc: "MakeFile [-cmyb] inFileNameRoot [leftMarg [printWidth]] -- Create disk file for Diablo C150 from AIS sources."];
END.