-- Print Labels.mesa
-- Edited by Sweet, 2-Oct-82 21:45:30
DIRECTORY
AltoFileDefs,
Ascii,
Inline,
IODefs,
ImageDefs,
MiscDefs,
PressDefs,
PressUtilities,
SegmentDefs,
Storage,
StreamDefs,
String;
PrintLabels: PROGRAM
IMPORTS
ImageDefs, Inline, IODefs, MiscDefs, PressDefs,
PressUtilities, SegmentDefs, Storage, StreamDefs, String =
BEGIN OPEN IODefs, PressDefs, String, StreamDefs;
in: StreamHandle;
Label: TYPE = BASE POINTER TO LabelBody;
RelLabel: TYPE = Label RELATIVE POINTER TO StringBody;
LabelBody: TYPE = RECORD [
count, last: [0..256),
lines: ARRAY [0..8) OF RelLabel];
nextRP: RelLabel;
AddLine: PROC =
BEGIN
s: STRING = @buffer[nextRP];
s↑ ← [length: 0, maxlength: line.length, text: NULL];
String.AppendString[s, line];
buffer.lines[buffer.count] ← nextRP;
nextRP ← nextRP + String.WordsForString[line.length];
WHILE s.length # 0 AND s[s.length-1] = Ascii.SP DO
s.length ← s.length - 1;
ENDLOOP;
IF ~slashSeen AND line[0] = '/ THEN {
slashSeen ← TRUE; buffer.last ← buffer.count};
buffer.count ← buffer.count + 1;
END;
StartLabel: PROC =
BEGIN
buffer.count ← 0; buffer.last ← 0;
slashSeen ← FALSE;
nextRP ← LOOPHOLE[SIZE[LabelBody]];
END;
slashSeen: BOOLEAN;
pfdBody: PressFileDescriptor;
pfd: POINTER TO PressFileDescriptor = @pfdBody;
Mica: TYPE = CARDINAL;
MBox: TYPE = RECORD [x,y,w,h: Mica];
CharHeight: Mica;
CharWidth: POINTER TO ARRAY CHARACTER OF Mica;
TextCharWidth: ARRAY CHARACTER OF Mica;
TextCharHeight: Mica;
PointsToMicas: PROC [points: CARDINAL] RETURNS [Mica] =
{RETURN [Inline.LongDiv[Inline.LongMult[points, MicasPerInch],72]]};
StringWidth: PROC [s: STRING] RETURNS [l: Mica] =
BEGIN
l ← 0;
FOR i: CARDINAL IN [0..s.length) DO
l ← l + CharWidth[s[i]];
ENDLOOP;
END;
LineY: PROC [box: POINTER TO MBox, line, of: CARDINAL, lead: Mica ← 0]
RETURNS [Mica] =
BEGIN
h: Mica = CharHeight;
bottom: Mica;
line ← of-1-line; -- count from top
bottom ← (box.h- of*h - (of-1)*lead)/2;
RETURN [box.y + bottom + (line-1)*(h+lead)];
END;
LJLine: PROC [s: STRING, box: POINTER TO MBox, line, of: CARDINAL, lead: Mica ← 1] =
BEGIN
y: Mica = LineY[box: box, line: line, of: of, lead: lead];
PutText[pfd, s, box.x, y];
END;
P1: Mica = PointsToMicas[1];
P2: Mica = PointsToMicas[2];
M1: Mica = MicasPerInch;
M12: Mica = MicasPerInch/2;
M14: Mica = MicasPerInch/4;
M34: Mica = (3*MicasPerInch)/4;
M38: Mica = (3*MicasPerInch)/8;
TextFont: PROC =
BEGIN
SetFont[p: pfd, Name: "Helvetica", PointSize: outPointSize, Face: 0];
CharHeight ← TextCharHeight;
CharWidth ← @TextCharWidth;
END;
outPointSize: CARDINAL ← 10;
DigestFonts: PROC =
BEGIN
[] ← PressUtilities.FindFontWidths[
family: "Helvetica"L,
points: outPointSize,
weight: medium,
slope: regular,
widths: LOOPHOLE[@TextCharWidth]];
TextCharHeight ← PointsToMicas[outPointSize];
END;
commandStream: StreamHandle;
SetUpCommands: PROCEDURE =
BEGIN
cfa: POINTER TO AltoFileDefs.CFA ← MiscDefs.CommandLineCFA[];
cfile: SegmentDefs.FileHandle ← SegmentDefs.InsertFile[@cfa.fp,Read];
commandStream ← NIL;
commandStream ← CreateByteStream[cfile,Read
! SegmentDefs.InvalidFP => CONTINUE];
IF commandStream # NIL THEN
BEGIN
JumpToFA[commandStream,@cfa.fa];
WHILE commandStream.get[commandStream
! StreamError => GOTO nocommands] <= SP DO
NULL ENDLOOP;
SetIndex[commandStream,ModifyIndex[GetIndex[commandStream],-1]];
EXITS nocommands =>
BEGIN commandStream.destroy[commandStream]; commandStream ← NIL END;
END;
END;
ReadName: PROCEDURE [s: STRING] =
BEGIN
c: CHARACTER;
IF commandStream = NIL THEN ReadID[s]
ELSE
BEGIN
s.length ← 0;
DO
IF (c←commandStream.get[commandStream
! StreamError => GOTO endoffile]) <= SP THEN
BEGIN IF s.length # 0 THEN EXIT END
ELSE BEGIN String.AppendChar[s,c]; WriteChar[c] END;
REPEAT endoffile =>
BEGIN commandStream.destroy[commandStream]; commandStream ← NIL END;
ENDLOOP;
END;
END;
GetFile: PROCEDURE [prompt: STRING, access: AccessOptions, switches: STRING ← NIL] RETURNS [StreamHandle] =
BEGIN
name: STRING ← [40];
WriteString[prompt];
ReadName[name];
IF switches # NIL THEN FOR i:CARDINAL IN[0..name.length) DO
IF name[i] = '/ THEN
BEGIN
FOR j: CARDINAL IN (i..name.length) DO
String.AppendChar[switches,name[j]] ENDLOOP;
name.length ← i;
EXIT;
END;
ENDLOOP;
WriteChar[CR];
IF name.length = 0 THEN ImageDefs.StopMesa[];
RETURN[NewByteStream[name,access]]
END;
ReadLabel: PROC =
BEGIN
StartLabel[];
DO
ReadLine[];
IF line.length = 0 AND (buffer.count # 0 OR in.endof[in]) THEN EXIT;
IF line.length # 0 THEN AddLine[];
ENDLOOP;
IF ~slashSeen THEN buffer.last ← buffer.count;
END;
ReadLine: PROC =
BEGIN
c: CHARACTER;
n: CARDINAL ← 0;
line.length ← 0;
BEGIN
DO
c ← in.get[in ! StreamError => EXIT];
IF c = CR THEN EXIT;
IF n = line.maxlength-1 THEN GO TO tooLong;
line[n] ← c;
n ← n + 1;
ENDLOOP;
line.length ← n;
EXITS
tooLong => {
IODefs.WriteLine["Line truncated:"L];
IODefs.WriteLine[line];
line.length ← n};
END;
END;
line: STRING ← [200];
row, col: CARDINAL;
LWidth: Mica = (8*M1 + M12)/3;
LHeight: Mica = M1;
yDelta: Mica ← 0;
scaleFactor: CARDINAL ← 100;
Scale: PROC [d: Mica] RETURNS [Mica] = { -- d must be > 0
RETURN [Inline.LongDiv[Inline.LongMult[d, scaleFactor], 100]]};
PressLabel: PROC [p: Label] =
BEGIN
name: STRING = [100];
l1: STRING = @p[p.lines[0]];
comma: CARDINAL ← l1.length;
j: CARDINAL;
box: MBox;
IF row = 11 THEN {row ← 0; col ← col + 1};
IF col = 3 THEN {WritePage[pfd]; col ← 0};
box.x ← M38 + col * LWidth;
box.y ← yDelta + 10*M1 - Scale[row*LHeight];
box.w ← LWidth - M38;
box.h ← M1;
FOR i: CARDINAL IN [0..l1.length) DO
IF l1[i] = ', THEN {comma ← i; EXIT};
ENDLOOP;
j ← comma + 1;
WHILE j < l1.length AND l1[j] = Ascii.SP DO j ← j + 1; ENDLOOP;
FOR i: CARDINAL IN [j..l1.length) DO
String.AppendChar[name, l1[i]];
ENDLOOP;
IF name.length # 0 AND name[name.length-1] # Ascii.SP THEN
String.AppendChar[name, Ascii.SP];
FOR i: CARDINAL IN [0..comma) DO
String.AppendChar[name, l1[i]];
ENDLOOP;
LJLine[s: name, box: @box, line: 0, of: p.last];
FOR i: CARDINAL IN [1..p.last) DO
LJLine[s: @p[p.lines[i]], box: @box, line: i, of: p.last];
ENDLOOP;
row ← row + 1;
END;
InitPressThings: PROC =
BEGIN
InitPressFileDescriptor[pfd, "Labels.press"];
DigestFonts[];
TextFont[];
row ← col ← 0;
END;
buffer: Label;
makePress, paginateList: BOOLEAN ← FALSE;
DoIt: PROC =
BEGIN
c: CHARACTER;
switches: STRING ← [20];
BEGIN
i: CARDINAL;
GetSwitchNumber: PROC RETURNS [INTEGER] =
BEGIN
neg: BOOLEAN ← FALSE;
n: CARDINAL ← 0;
i ← i+1;
IF switches[i] = '- THEN {neg ← TRUE; i ← i+1};
WHILE switches[i] IN ['0..'9] DO
n ← n * 10 + (switches[i] - '0);
i ← i+1;
ENDLOOP;
i ← i-1; -- since loop increments at bottom
IF neg THEN RETURN [-INTEGER[n]] ELSE RETURN [n];
END;
in ← GetFile["input: "L, StreamDefs.Read, switches !
SegmentDefs.FileNameError => GO TO cantFind];
i ← 0;
WHILE i < switches.length DO
SELECT (c ← switches[i]) FROM
's, 'S => scaleFactor ← GetSwitchNumber[];
'y, 'Y => yDelta ← GetSwitchNumber[];
'p, 'P => outPointSize ← GetSwitchNumber[];
ENDCASE => GO TO badSwitch;
i ← i+1;
ENDLOOP;
buffer ← Storage.Pages[3];
InitPressThings[];
-- go through list of names, calling PressLabel
DO
ReadLabel[];
IF buffer.count = 0 THEN EXIT;
PressLabel[buffer];
ENDLOOP;
in.destroy[in];
WritePage[pfd];
ClosePressFile[pfd];
Storage.FreePages[buffer];
IODefs.WriteLine["--done"L];
EXITS
cantFind => WriteLine[" file not found"L];
badSwitch => WriteLine[" bad switch"L];
END;
END;
SetUpCommands[];
DoIt[];
ImageDefs.StopMesa[];
END.